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;
}

浙公网安备 33010602011771号