poj 2186
首先,强连通分量可以缩点,所有缩点后的图一定是一个有向无环图,出度为0的点受其他出度不为0的点的仰慕.因为要求的是受其他所有点仰慕的点的个数(强连通内互相仰慕),所以,当只有一个出度为0的点时,输出它所在的强连通分量的顶点个数就是答案.
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define _Clr(x, y) memset(x, y, sizeof(x)) 6 #define INF 0x3f3f3f3f 7 #define N 10010 8 using namespace std; 9 10 struct Node 11 { 12 int to, next; 13 }edge[N*5]; 14 int head[N], tot; 15 int dfn[N], low[N]; 16 int Sta[N], bleg[N]; 17 int num[N], n; 18 bool instack[N]; 19 int cnt, ght, top; 20 21 void Init() 22 { 23 cnt=tot=ght=top=0; 24 _Clr(head, -1); 25 _Clr(dfn, 0); 26 _Clr(instack, 0); 27 _Clr(num, 0); 28 } 29 30 void Add_edge(int a, int b) 31 { 32 edge[tot].to = b; 33 edge[tot].next = head[a]; 34 head[a] = tot++; 35 } 36 37 void dfs(int u) 38 { 39 dfn[u]=low[u]=++cnt; 40 Sta[top++] = u; 41 instack[u] = true; 42 for(int i=head[u]; i!=-1; i=edge[i].next) 43 { 44 int v = edge[i].to; 45 if(!dfn[v]) 46 { 47 dfs(v); 48 low[u] = min(low[u], low[v]); 49 } 50 else if(instack[v]) low[u] = min(low[u], dfn[v]); 51 } 52 if(low[u] == dfn[u]) 53 { 54 ght++; 55 int v; 56 do 57 { 58 v = Sta[--top]; 59 instack[v] = false; 60 bleg[v] = ght; 61 num[ght]++; //num[i]表示第i个强连通分量的顶点数 62 }while(u!=v); 63 } 64 } 65 66 int outdeg[N]; 67 void Tarjan() 68 { 69 for(int i=1; i<=n; i++) 70 if(!dfn[i]) dfs(i); 71 72 _Clr(outdeg, 0); 73 74 // 缩点求出度 75 for(int u=1; u<=n; u++) 76 for(int i=head[u]; i!=-1; i=edge[i].next) 77 { 78 int v = edge[i].to; 79 if(bleg[v]!=bleg[u]) outdeg[bleg[u]]++; 80 } 81 82 int ans=0, index; 83 for(int i=1; i<=ght; i++) 84 if(outdeg[i]==0) 85 ans++, index=i; 86 printf("%d\n", ans==1?num[index]:0); 87 } 88 89 int main() 90 { 91 int m, a, b; 92 while(~scanf("%d%d", &n, &m)) 93 { 94 Init(); 95 while(m--) 96 { 97 scanf("%d%d", &a, &b); 98 Add_edge(a, b); 99 } 100 Tarjan(); 101 } 102 return 0; 103 }