大致思路:算出有多少个强连通分量,再进行缩点处理
再判断出度为零的缩点是否唯一
#include<string.h>
#include<stdio.h>
#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
#define M 10005
vector<int> G[M];//二维邻接表
int n,m;//点数 边数
int index;//时间戳
int ncolor;//颜色的数量,即强连通分量的个数
int dfn[M],low[M];
int color[M];//每个点的颜色
int Outdegree[M];//缩点的出度
bool instack[M];//是否在栈内的标志
stack<int> st;
void Tarjan(int u)
{
int i;
if(dfn[u]!=0)
return ;
dfn[u]=low[u]=index++;
st.push(u);
instack[u]=true;
for(i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!dfn[v])
{
Tarjan(v);
if(low[u]>low[v])
low[u]=low[v];
}
else if(instack[v]==true&&low[u]>dfn[v])
low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
int v;
ncolor++;
do{
v=st.top();
st.pop();
color[v]=ncolor;
instack[v]=false;
}while(u!=v);
}
}
void solve()
{
int nzeronum=0;
int zerocolor=0;
int i,j,v,num=0;
if(ncolor==1)
{
printf("%d\n",n);
return;
}
memset(Outdegree,0,sizeof(Outdegree));
for(i=1;i<=n;i++)
{
if(Outdegree[color[i]])
continue;
for(j=0;j<G[i].size();j++)
{
v=G[i][j];
if(color[i]!=color[v])
Outdegree[color[i]]=1;
}
}
for(i=1;i<=ncolor;i++)
if(Outdegree[i]==0)
{
nzeronum++;
zerocolor=i;
if(nzeronum>1)
break;
}
if(nzeronum>1)
{
printf("0\n");
return;
}
for(i=1;i<=n;i++)
if(color[i]==zerocolor)
num++;
printf("%d\n",num);
return;
}
int main()
{
int i,j;
//freopen("C:\\Users\\y460\\Desktop\\stdout.txt","w",stdout);
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
G[a].push_back(b);
}
memset(dfn,0,sizeof(dfn));
memset(color,0,sizeof(color));
memset(instack,false,sizeof(instack));
index=1;
ncolor=0;
for(i=1;i<=n;i++)
Tarjan(i);
solve();
//scanf("%d",&i);
return 0;
}