poj 2186 Popular Cows
http://poj.org/problem?id=2186
题意:若A认为B好,且B又认为C好,则可以推出A认为C好,现给一个这样的无向关系图,求出有多少个点,所有人都认为它好。
思路:先对图进行tarjan去环缩边成点,并统计环中点的个数,然后查看一下出度为0的点是否为1,如果是则这个点代表的环里的点的数目,否则puts("0");

#include<stdio.h> #include<string.h> #include<iostream> #include<stack> #include<utility> using namespace std; const int maxn = 10005; struct nd { int u,v,next; }edge[maxn*5]; int head[maxn],ecnt,cnt,idx; int dfn[maxn],low[maxn],vis[maxn],belong[maxn],c[maxn],out[maxn]; stack<int>st; void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int u) { int i,v; dfn[u] = low[u] = ++idx; vis[u] = 1; st.push(u); for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]){ tarjan(v); low[u] = min(low[v],low[u]); }else if(vis[v]) low[u] = min(dfn[v],low[u]); } if(dfn[u] == low[u]) { cnt++; do{ v = st.top(); st.pop(); vis[v] = 0; belong[v] = cnt; c[cnt]++; }while(v!=u); } } int main() { int i,j,k,t,n,m,u,v; while(scanf("%d %d",&n,&m)==2) { memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(c,0,sizeof(c)); memset(belong,0,sizeof(belong)); memset(out,0,sizeof(out)); ecnt = 0; idx = 0; cnt = 0; for(i = 0; i < m; ++ i) { scanf("%d %d",&u,&v); add(u,v); } for(i = 1; i <= n; ++ i) if(!dfn[i]) tarjan(i); for(i = 0; i < ecnt; ++ i) { u = belong[edge[i].u]; v = belong[edge[i].v]; if(v!=u)out[u]++; } k = 0; for(i = 1; i <= cnt; ++ i) if(!out[i]){k++;j=i;} if(k!=1)puts("0"); else printf("%d\n",c[j]); } return 0; }
下面代码过不了,不知道为什么?求解中~~~

#include<stdio.h> #include<string.h> #include<iostream> #include<stack> #include<utility> using namespace std; const int maxn = 10005; struct nd { int u,v,next; }edge[maxn*5]; int head[maxn],ecnt,cnt,idx; int dfn[maxn],low[maxn],vis[maxn],belong[maxn],c[maxn],in[maxn]; stack<int>st; void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int u) { int i,v; dfn[u] = low[u] = ++idx; vis[u] = 1; st.push(u); for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]){ tarjan(v); low[u] = min(low[v],low[u]); }else if(vis[v]) low[u] = min(dfn[v],low[u]); } if(dfn[u] == low[u]) { cnt++; do{ v = st.top(); st.pop(); vis[v] = 0; belong[v] = cnt; c[cnt]++; }while(v!=u); } } int dfs(int x) { int i,j,k = 0,v; for(i = head[x]; i != -1; i = edge[i].next) { j = edge[i].v; in[j]--; if(!in[j]) {k++;v=j;} if(k>1) return 0; } if(k)return dfs(v); return c[x]; } int main() { int i,j,k,t,n,m,u,v; while(scanf("%d %d",&n,&m)==2) { memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(c,0,sizeof(c)); memset(belong,0,sizeof(belong)); memset(in,0,sizeof(in)); ecnt = 0; idx = 0; cnt = 0; for(i = 0; i < m; ++ i) { scanf("%d %d",&u,&v); if(u!=v) add(u,v); } for(i = 1; i <= n; ++ i) if(!dfn[i]) tarjan(i); k = ecnt; ecnt = 0; memset(head,-1,sizeof(head)); for(i = 0; i < k; ++ i) { u = belong[edge[i].u]; v = belong[edge[i].v]; if(v!=u) { add(u,v); in[v]++;} } k = 0; for(i = 1; i <= cnt; ++ i) if(!in[i]){k++;j=i;} if(k!=1)puts("0"); else printf("%d\n",dfs(j)); } return 0; }