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
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 }
高考结束,重新回归。