POJ 2186 Popular Cows tarjan+缩点
http://poj.org/problem?id=2186
题意:牛搞个人崇拜(怎么又是牛??牛很圣神?),还具有传递性 如果A崇拜B B崇拜C 则A崇拜 C ,求受所有牛崇拜的牛的数量
解法:在强连通分量里面,每个牛相互崇拜,把强连通分量缩为一个点,缩点后的图 为一个强连通分量 或者
一个 弱连通分量 总之最后出度为零的缩点 受所有的牛崇拜
有一个地方:缩点时候可能会出现 多条同向的重边
图
缩点后 第一个缩点 到第二个缩点 有两条有向线
所以最后用 in[]入度不好求 out[]为0的点只有一个的时候就找到答案了
代码:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #define Min(a,b)a<b?a:b #define nMAX 10005 #define mMAX 50005 using namespace std; int head[nMAX],dfn[nMAX],low[nMAX],stack[nMAX],node_sta[nMAX]; int out[nMAX],belon[nMAX]; int n,top,s_edge,atype,times; bool insta[nMAX]; struct Edge { int to,next; }edge[mMAX]; void addedge(int u,int v) { s_edge++; edge[s_edge].to=v; edge[s_edge].next=head[u]; head[u]=s_edge; return ; } void tarjan(int u) { dfn[u]=++times; low[u]=times; stack[++top]=u; insta[u]=1; int e,v; for(e=head[u];e;e=edge[e].next) { v=edge[e].to; if(!dfn[v]) { tarjan(v); low[u]=Min(low[u],low[v]); } else if(insta[v]) low[u]=Min(low[u],dfn[v]); } int j; if(low[u]==dfn[u]) { atype++; do { j=stack[top--]; insta[j]=0; belon[j]=atype; node_sta[atype]++; }while(j!=u); } return ; } void init() { s_edge=0; top=0; atype=0; times=0; memset(head,0,sizeof(head)); memset(insta,0,sizeof(insta)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(node_sta,0,sizeof(node_sta)); memset(belon,0,sizeof(belon)); memset(out,0,sizeof(out)); return ; } int main() { int m,u,v,i; while(~scanf("%d%d",&n,&m)) { init(); while(m--) { scanf("%d%d",&u,&v); addedge(u,v); } for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i); //缩点 int e,v; for(i=1;i<=n;i++) for(e=head[i];e;e=edge[e].next) { v=edge[e].to; if(belon[i]!=belon[v]) out[belon[i]]++; } int ans=0,num=0; for(i=1;i<=atype;i++) if(out[i]==0) { ans=node_sta[i]; num++; } if(num>1) printf("0\n"); else printf("%d\n",ans); } return 0; }