poj 2186 popular cows 强连通缩点

来源:互联网 发布:某企业调查用户从网络 编辑:程序博客网 时间:2024/04/29 12:22
//缩点后必须只有一个点的出度为0,此连通块中的点才被所有的牛仰慕//poj 2186#include<stdio.h>#include<string.h>#include<vector>#include<algorithm>using namespace std;const int MAX = 10010;vector<int> edge[MAX];int st[MAX];int dfn[MAX],low[MAX];int top,btype,tdfn;//btype:连通块的个数int belong[MAX];//点属于哪个连通块bool ins[MAX];void dfs(int s){int i,t;dfn[s]=low[s]=++tdfn;ins[s]=true;st[++top]=s;for(i=0;i<edge[s].size();i++){t=edge[s][i];if(!dfn[t]){dfs(t);if(low[t]<low[s]) low[s]=low[t];}else if(ins[t] && dfn[t]<low[s])  low[s]=dfn[t];}if(dfn[s]==low[s]){btype++;do{t=st[top--];ins[t]=false;belong[t]=btype;}while(t!=s);}}void SCC(int n){int i;top=btype=tdfn=0;memset(ins,false,sizeof(ins));memset(dfn,0,sizeof(dfn));for(i=1;i<=n;i++)if(!dfn[i])dfs(i);}int chu[MAX];int cnt[MAX];//某个连通块有几个点int main(){    int i,j,k;int n,m;int a,b;while(scanf("%d%d",&n,&m)!=EOF){for(i=0;i<m;i++){scanf("%d%d",&a,&b);edge[a].push_back(b);}SCC(n);memset(chu,0,sizeof(chu));memset(cnt,0,sizeof(cnt));for(i=1;i<=n;i++){int tmp=belong[i];cnt[tmp]++;for(j=0;j<edge[i].size();j++){if(belong[i]!=belong[edge[i][j]])//一条边的两个点属于不同的连通块chu[tmp]++;}}int sum=0;int ans;for(i=1;i<=btype;i++) if(chu[i]==0){sum++;ans=i;}if(sum>1) printf("0\n");else printf("%d\n",cnt[ans]);}return 0;}