题意:一共有n头牛,m条崇拜关系,并且崇拜关系是可以传递的,偶像的偶像也是自己的偶像,求被除自己以外被其他所有牛崇拜的牛的数量。
题解:将强连通图缩成点,找到出度为0的点,如果有2个及以上就不能达成条件,如果只有一个,那么代表着其他点都有出去的边,且因为强连通锁点了,所以定不存在环,肯定至少有一条边指到出度为0的点
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int N = 1e4+5; 7 struct Node 8 { 9 int nt; 10 int to; 11 }E[N*5]; 12 int head[N], vis[N], in[N], Stack[N*5], rt[N], low[N], dfn[N], du[N]; 13 int tot = 0, n, m, cnt = 0, top = 0, rtcnt = 0; 14 void Add_edge(int u, int v) 15 { 16 E[tot].to = v; 17 E[tot].nt = head[u]; 18 head[u] = tot++; 19 } 20 void Tarjan(int u) 21 { 22 vis[u] = in[u] = 1; 23 low[u] = dfn[u] = ++cnt; 24 Stack[++top] = u; 25 for(int i = head[u]; ~i; i = E[i].nt) 26 { 27 int v = E[i].to; 28 if(!vis[v]) 29 Tarjan(v); 30 if(in[v]) 31 low[u] = min(low[v],low[u]);//这里是更新点u,因为先被访问的点肯定low值小,所以反过来是肯定更新不了的 32 } 33 if(low[u] == dfn[u]) 34 { 35 int v; 36 do 37 { 38 v = Stack[top--]; 39 in[v] = 0; 40 rt[v] = rtcnt; 41 }while(v != u); 42 rtcnt++; 43 } 44 } 45 int main() 46 { 47 memset(head, -1, sizeof(head)); 48 memset(du, 0, sizeof(du)); 49 memset(vis, 0, sizeof(vis)); 50 scanf("%d%d",&n,&m); 51 int u, v; 52 for(int i = 0; i < m; i++) 53 { 54 scanf("%d%d",&u,&v); 55 Add_edge(u,v); 56 } 57 for(int i = 1; i <= n; i++) 58 if(!vis[i]) Tarjan(i); 59 for(int i = 1; i <= n; i++) 60 { 61 for(int j = head[i]; ~j; j = E[j].nt) 62 { 63 int v = E[j].to; 64 if(rt[v] != rt[i]) 65 du[rt[i]]++; 66 } 67 } 68 int cnt_in = 0, ans_rt; 69 for(int i = 0; i < rtcnt; i++ ) 70 { 71 if(du[i] == 0) cnt_in++, ans_rt = i; 72 } 73 if(cnt_in == 1) 74 { 75 int ans = 0; 76 for(int i = 1; i <= n; i++) 77 { 78 if(ans_rt == rt[i]) ans++; 79 } 80 printf("%d ",ans); 81 } 82 else printf("0 "); 83 84 return 0; 85 }