BZOJ 1051 受欢迎的牛

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

很明显,tarjan缩点+topsort,然后bitset大法好。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<bitset>
 5 #include<queue>
 6 #include<stack>
 7 #include<cstdlib>
 8 using namespace std;
 9 
10 #define maxn 10010
11 #define maxm 60010
12 int n,m,cnt,tot,dfn[maxn],low[maxn],id[maxn],d[maxn];
13 int side[maxn],toit[maxm],next[maxm];
14 int nside[maxn],ntoit[maxm],nnext[maxm];
15 stack <int> S; bitset <maxn> bit[maxn]; bool vis[maxn];
16 
17 inline void add(int a,int b) { next[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b; }
18 
19 inline void ins(int a,int b)
20 {
21     nnext[++cnt] = nside[a]; ++d[b];
22     nside[a] = cnt; ntoit[cnt] = b;
23 }
24 
25 inline void dfs(int now)
26 {
27     S.push(now); dfn[now] = low[now] = ++cnt;
28     for (int i = side[now];i;i = next[i])
29         if (!vis[toit[i]])
30         {
31             if (!dfn[toit[i]]) dfs(toit[i]);
32             low[now] = min(low[toit[i]],low[now]);
33         }
34     if (dfn[now] == low[now])
35     {
36         ++tot;
37         while (S.top() != now) vis[S.top()] = true,id[S.top()] = tot,S.pop();
38         vis[S.top()] = true,id[S.top()] = tot,S.pop();
39     }
40 }
41 
42 inline void rebuild()
43 {
44     cnt = 0;
45     for (int i = 1;i <= n;++i)
46     {
47         bit[id[i]].set(i-1);
48         for (int j = side[i];j;j = next[j])
49             if (id[i] != id[toit[j]]) ins(id[i],id[toit[j]]);
50     }
51 }
52 
53 inline void topsort()
54 {
55     queue <int> team;
56     for (int i = 1;i <= tot;++i) if (!d[i]) team.push(i);
57     while (!team.empty())
58     {
59         int now = team.front(); team.pop();
60         for (int i = nside[now];i;i = nnext[i])
61         {
62             bit[ntoit[i]] |= bit[now];
63             if (!--d[ntoit[i]]) team.push(ntoit[i]);
64         }
65     }
66     int ans = 0;
67     for (int i = 1;i <= n;++i) if (bit[id[i]].count() == n) ++ans;
68     printf("%d",ans);
69 }
70 
71 int main()
72 {
73     freopen("1051.in","r",stdin);
74     freopen("1051.out","w",stdout);
75     scanf("%d %d",&n,&m);
76     for (int i = 1;i <= n;++i) add(i,i);
77     while (m--) { int a,b; scanf("%d %d",&a,&b); add(a,b); }
78     cnt = 0;
79     for (int i = 1;i <= n;++i) if (!dfn[i]) dfs(i);
80     rebuild();
81     topsort();
82     fclose(stdin); fclose(stdout);
83     return 0;
84 }
View Code
原文地址:https://www.cnblogs.com/mmlz/p/4280516.html