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
",ans);
		}
		else printf("0
");
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4292294.html