题目大意:给出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 答案就是该分量中牛的个数.
代码如下:
#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; }