POJ 2186
缩点求出度为0的点即可。当求出只有一点时,表示存在解,否则不存在解。注意缩点后的一点其实是有很多点的。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string.h> using namespace std; const int N=10005; const int M=50025; int head[N],beg[N],deg[N]; struct ei{ int u,v,next; }edge[M]; int tot,n,m; int dfn[N],low[N]; bool instack[N]; int stack[N],stot,index,mark; void tarjan(int u) { dfn[u]=low[u]=++index; stack[++stot]=u; instack[u]=true; for (int e=head[u];e!=-1;e=edge[e].next ){ int v=edge[e].v; if (dfn[v]==-1) { tarjan(v); low[u] = min(low[u], low[v]) ; } else if (instack[v]) { low[u] = min(low[u], dfn[v]) ; } } int v; if (dfn[u] == low[u]) { mark++; do{ v = stack[stot--]; beg[v]=mark; instack[v]=false; }while(u!= v); } } void addedge(int u,int v){ edge[tot].u=u; edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++; } int main(){ int u,v; while(scanf("%d%d",&n,&m)!=EOF){ tot=index=mark=0; memset(head,-1,sizeof(head)); for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); addedge(u,v); } memset(dfn,-1,sizeof(dfn)); memset(low,-1,sizeof(low)); memset(instack,false,sizeof(instack)); stot=0; for(int i=1;i<=n;i++){ if(dfn[i]==-1){ tarjan(i); } } memset(deg,0,sizeof(deg)); for(int i=0;i<tot;i++){ u=edge[i].u; v=edge[i].v; if(beg[u]!=beg[v]) deg[beg[u]]++; } int cnt=0,ap; for(int i=1;i<=mark;i++){ if(!deg[i]){ ap=i; cnt++; } } int ans=0; if(cnt==1){ for(int i=1;i<=n;i++){ if(beg[i]==ap) ans++; } printf("%d\n",ans); } else printf("0\n"); } return 0; }