【模板】Tarjan缩点,强连通分量 洛谷P2341 [HAOI2006]受欢迎的牛 [2017年6月计划 强连通分量01]
P2341 [HAOI2006]受欢迎的牛
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜
欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你
算出有多少头奶牛可以当明星。
输入输出格式
输入格式: 第一行:两个用空格分开的整数:N和M
第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B
输出格式: 第一行:单独一个整数,表示明星奶牛的数量
输入输出样例
输入样例#1:
3 3 1 2 2 1 2 3
输出样例#1:
1
说明
只有 3 号奶牛可以做明星
【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
模板题,出度为零的点有且仅有一个才有解,解即为该点内的点数。
1 #include <bits/stdc++.h> 2 const int INF = 0x3f3f3f3f; 3 const int MAXN = 10000 + 10; 4 const int MAXM = 50000 + 10; 5 inline int read(int &x){ 6 x = 0;char ch = getchar();char c = ch; 7 while(ch > '9' || ch < '0')c = ch, ch = getchar(); 8 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0',ch = getchar(); 9 if(c == '-') x = -x; 10 } 11 inline int min(int a,int b){return a > b? b : a;} 12 int n,m,tmp1,tmp2,cnt,cnt2,head[MAXN],head2[MAXN]; 13 int dfn[MAXN],low[MAXN], group, num[MAXN],belong[MAXN], t, stack[MAXN], top; 14 bool b[MAXN],bb[MAXN]; 15 struct Edge{int u,v,next;}edge[MAXM],edge2[MAXM]; 16 void insert(int a,int b){edge[++cnt] = Edge{a, b, head[a]};head[a] = cnt;} 17 void insert2(int a,int b){edge2[++cnt2] = Edge{a, b, head2[a]};head2[a] = cnt2;} 18 void dfs(int u){ 19 int now = -1; 20 b[u] = true;bb[u] = true; 21 dfn[u] = low[u] = ++t; 22 stack[++top] = u; 23 for(int pos = head[u];pos;pos = edge[pos].next){ 24 int v = edge[pos].v; 25 if(!b[v]){ 26 dfs(v); 27 if(low[u] > low[v])low[u] = low[v]; 28 } 29 else if(bb[v] && low[u] > dfn[v]){ 30 low[u] = dfn[v]; 31 } 32 } 33 if(low[u] == dfn[u]){ 34 group ++; 35 while(now != u){ 36 now = stack[top --]; 37 bb[now] = false; 38 belong[now] = group; 39 num[group] ++; 40 } 41 } 42 } 43 inline void rebuild(){ 44 for(int u = 1;u <= n;u ++){ 45 for(int pos = head[u];pos;pos = edge[pos].next){ 46 int v = edge[pos].v; 47 if(belong[u] != belong[v]){ 48 insert2(belong[u], belong[v]); 49 } 50 } 51 } 52 } 53 inline void tarjan(){ 54 for(int i = 1;i <= n;i ++)if(!b[i])dfs(i); 55 rebuild(); 56 } 57 int ans; 58 int main(){ 59 read(n);read(m); 60 for(int i = 1;i <= m;i ++){ 61 read(tmp1);read(tmp2);insert(tmp1, tmp2); 62 } 63 tarjan(); 64 for(int i = 1;i <= group;i ++){ 65 if(!head2[i]){ 66 if(ans) ans = 0;break; 67 else ans = num[i]; 68 } 69 } 70 printf("%d", ans); 71 return 0; 72 }