题目还不能看,先贴代码过来
基本就是先强连通分量缩点,
然后统计一下出度入度为零的点
code
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<vector>
#define N 10005
using namespace std;
struct Edge
{
int dest;
Edge *next;
}*GA[N],*GT[N],*G[N];
int used[N],path[N],part[N],m,n;
bool mark[N][N];
int in[N],out[N];
void addedge(Edge *T[],int i,int j)
{
Edge *L;
L=new Edge;
L->dest=j;
L->next=T[i];
T[i]=L;
}
void DFSA(int s)
{
Edge *l;
if(!used[s])
{
used[s]=1;
for(l=GA[s];l!=NULL;l=l->next)
DFSA(l->dest);
path[0]++;
path[path[0]]=s;
}
}
void DFST(int s)
{
Edge *l;
if(! used[s])
{
used[s]=1;
for(l=GT[s];l!=NULL;l=l->next)
DFST(l->dest);
part[s]=part[0];
}
}
void Kosaraju()
{
int i,j,k;
Edge *L;
memset(used ,0,sizeof(used));
path[0]=part[0]=0;
for(i=1;i<=n;i++)
DFSA(i);
memset(used,0,sizeof(used));
for(i=n;i>=1;i--)
{
if(!used[path[i]])
{
part[0]++;
DFST(path[i]);
}
}
memset(mark,0,sizeof(mark));
for(k=1;k<=n;k++)
{
for(L=GA[k],i=part[k];L!=NULL;L=L->next)
{
j=part[L->dest];
if(i!=j&&!mark[i][j])
{
mark[i][j]=1;
addedge(G,i,j);
}
}
}
}
int main()
{
int i,a,b;
Edge *L;
int t,mm;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&mm);
for(i=1;i<=n;i++)
GA[i]=GT[i]=G[i]=NULL;
while(mm--)
{
scanf("%d%d",&a,&b);
addedge(GA,a,b);
addedge(GT,b,a);
}
if(n==1){printf("0\n");continue;}
Kosaraju();
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(m=part[0],i=1;i<=m;i++)
{
for(L=G[i];L!=NULL;L=L->next)
{
out[i]++;
in[L->dest]++;
}
}
for(a=b=0,i=1;i<=m;i++)
{
if(!in[i]) a++;
if(!out[i]) b++;
}
b=a>b?a:b;
if(m==1) printf("0\n");
else printf("%d\n",b);
}
return 0;
}