【BZOJ 1051】[HAOI2006]受欢迎的牛

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3375  Solved: 1771
[Submit][Status][Discuss]

Description

每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。

Input

第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)

Output

一个数,即有多少头牛被所有的牛认为是受欢迎的。

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

HINT

100%的数据N<=10000,M<=50000

Source


ANALYSIS


我的思路很简单很暴力,先把环缩点变成DAG,然后按拓扑序递推支持人数。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 10005;
const int MAXM = 50005;

struct Edge
{
    int from, to, next;
    
    Edge() {
    }
    
    Edge(int u, int v) : from(u), to(v) {
    }
    
}edges[MAXM], edt[MAXM];

int n, m;
int first[MAXN], ft[MAXN], sccno[MAXN], dg[MAXN], bkn[MAXN], scc_cnt;
int topsort[MAXN], f[MAXN], toplen;
bool vis[MAXN];

void dfs1(int u)
{
    if (!vis[u]) return;
    vis[u] = false;
    for (int i = first[u]; i != -1; i = edges[i].next) dfs1(edges[i].to);
    topsort[toplen++] = u;
}

void dfs2(int u)
{
    if (sccno[u]) return;
    sccno[u] = scc_cnt;
    bkn[scc_cnt]++;
    for (int i = first[u]; i != -1; i = edges[i].next) dfs2(edges[i].to);
}

void dfs3(int u)
{
    if (!vis[u]) return;
    vis[u] = false;
    topsort[toplen++] = u;
    for (int i = ft[u]; i != -1; i = edt[i].next)
    {
        Edge &e = edt[i];
        dg[e.to]--;
        if (dg[e.to] == 0) dfs3(e.to);
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    memset(first, -1, sizeof(first));
    for (int i = 0; i < m; ++i)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        edges[i] = Edge(a, b);
        edges[i].next = first[a];
        first[a] = i;
    }
    memset(vis, true, sizeof(vis));
    scc_cnt = toplen = 0;
    for (int i = 1; i <= n; ++i) dfs1(i);
    memset(sccno, 0, sizeof(sccno));
    memset(bkn, 0, sizeof(bkn));
    for (int i = 0; i < n; ++i)
    if (!sccno[topsort[i]])
    {
        scc_cnt++;
        dfs2(topsort[i]);
    }
    memset(dg, 0, sizeof(dg));
    memset(ft, -1, sizeof(ft));
    int tots = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = first[i]; j != -1; j = edges[j].next)
        {
            Edge &e = edges[j];
            if (sccno[i] != sccno[e.to])
            {
                edt[tots] = Edge(sccno[i], sccno[e.to]);
                edt[tots].next = ft[sccno[i]];
                ft[sccno[i]] = tots++;
                dg[sccno[e.to]]++;
            }
        }
    memset(vis, true, sizeof(vis));
    toplen = 0;
    for (int i = 1; i <= scc_cnt; ++i)
        if (dg[i] == 0) dfs3(i);
    memset(f, 0, sizeof(f));
    for (int i = 0; i < scc_cnt; ++i)
        for (int j = ft[topsort[i]]; j != -1; j = edt[j].next)
        {
            Edge &e = edt[j];
            f[e.to] += f[topsort[i]] + bkn[topsort[i]];
        }
    int ans = 0;
    for (int i = 1; i <= n; ++i)
        if (f[sccno[i]] + bkn[sccno[i]] >= n) ans++;
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/albert7xie/p/5040396.html