使用Tarjan+縮點 完成,算是一道水題,但這題貌似不能用鄰接矩陣,會超內存,所以我使用了鏈表。
大概的思路就是求出所有的強聯通分量,然後把強聯通分量縮爲一個點,判斷這些新點的出度,如果只有一個出度爲0,則輸出這個點代表的聯通分量中所有點的個數;如果有多個出度爲0的點,則輸出0。
#include<iostream>
using namespace std;
const int MAXN =10001;
int DFN[MAXN];
int LOW[MAXN];
int instack[MAXN];
int Stap[MAXN];
int Belong[MAXN];
int num[MAXN];
int count[MAXN];
struct edge
{
int v,next;
}vetex[50001];
int head[MAXN];
int Stop,Bcnt,Dindex,N,k;
void add(int a,int b)
{
vetex[k].v = b;
vetex[k].next = head[a];
head[a] = k;k++;
}
void tarjan(int i)
{
int j;
DFN[i]=LOW[i]=++Dindex;
instack[i]=true;
Stap[++Stop]=i;
for (int k=head[i];k;k=vetex[k].next)
{
j=vetex[k].v;
if (!DFN[j])
{
tarjan(j);
if (LOW[j]<LOW[i])
LOW[i]=LOW[j];
}
else if (instack[j] && DFN[j]<LOW[i])
LOW[i]=DFN[j];
}
if (DFN[i]==LOW[i])
{
Bcnt++;
do
{
j=Stap[Stop--];
instack[j]=false;
Belong[j]=Bcnt;
}
while (j!=i);
}
}
void solve()
{
int i;
memset(num,0,sizeof(num));
Stop=Bcnt=Dindex=0;
memset(DFN,0,sizeof(DFN));
for (i=1;i<=N;i++)
if (!DFN[i])
tarjan(i);
}
int main()
{
int E;
while(cin>>N>>E)
{
k=1;
memset(head,false,sizeof(head));
for(int i=1;i!=E+1;i++)
{
int a,b;cin>>a>>b;
add(a,b);
}
solve();
//cout<<Bcnt<<endl;
memset(count,0,sizeof(count));
for(int i=1;i!=N+1;i++)
{
int t = Belong[i];
count[t]++;
for(int k=head[i];k;k=vetex[k].next)
if(t!=Belong[vetex[k].v])
num[t]++;
}
int flag(0),ans(0);
for(int i=1;i!=Bcnt+1;i++)
{
if(num[i]==0)
{
flag++;
ans+=count[i];
}
}
if(flag==1)
{
cout<<ans<<endl;
}
else
cout<<0<<endl;
}
return 0;
}