題目大意:給出N頭牛,有M種關係u, v。表明u牛崇拜v牛。要求找出有多少頭牛被全部牛崇拜着
題目連接:http://poj.org/problem?id=2186
解題思路:
1>求出強連通份量,標記每頭牛屬於哪一個份量內
2>進行縮點,計算連通份量的個數x,給出的M組關係從新構圖。u,v若屬不於一個連通份量內out[belong[u]]++;
3>統計x個連通份量出度。若是超過1個的連通份量出度爲0,證實兩羣牛互不崇拜;
若是等於1 答案就是該份量中牛的個數.node
代碼以下:ios
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define N 10005 #define M 50005 struct Edge { int v, next; }edge[M]; int node[N], stack[N], instack[N], dfn[N], out[N]; int low[N], belong[N], index, cnt_edge, n, m, cnt_tar, top; int ee[M][2]; void add_Edge(int u, int v) { edge[cnt_edge].next=node[u]; edge[cnt_edge].v=v; node[u]=cnt_edge++; } void tarjan(int u) { int i, j, v; dfn[u]=low[u]=++index; stack[++top]=u; instack[u]=1; for(i=node[u]; i!=-1; i=edge[i].next) { v=edge[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u], low[v]); } else if(instack[v]) low[u]=min(low[u], dfn[v]); } if(dfn[u]==low[u]) { cnt_tar++; do { j=stack[top--]; instack[j]=0; belong[j]=cnt_tar; }while(j!=u); } } void solve() { int i; top=0, index=0, cnt_tar=0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); for(i=1; i<=n; i++) if(!dfn[i]) tarjan(i); } int main() { int i, u, v; while(scanf("%d%d", &n, &m)!=EOF) { cnt_edge=0; memset(node, -1, sizeof(node)); for(i=1; i<=m; i++) { scanf("%d%d", &u, &v); ee[i][0]=u, ee[i][1]=v; add_Edge(u, v); } solve(); for(i=1; i<=m; i++) { int xx=belong[ee[i][0]], yy=belong[ee[i][1]]; if(xx!=yy) out[xx]++; } int mark=0, tot=0; for(i=1; i<=cnt_tar; i++) if(out[i]==0) { tot++; mark=i; } if(tot>1) printf("0\n"); else if(tot==1) { tot=0; for(i=1; i<=n; i++) if(belong[i]==mark) tot++; printf("%d\n", tot); } } return 0; }