题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3639
题解:将强连通分量缩成一个点,反向建图,对每个入度为0的点DFS,找出最大值即可。
#include <cstdio>
#include <cstring>
#include <vector>
#define MAXN 5001
using namespace std;
struct node
{
int to,next;
}edge[30001];
vector<int>mp[MAXN];
int belong[MAXN],num[MAXN],maxans[MAXN];
int head[MAXN],instack[MAXN],low[MAXN],dfn[MAXN];
int stack[MAXN],tot,Dindex,top,Bcnt,n,indegree[MAXN];
void Init(int n)
{//初始化
int i;
tot=0,top=0,Dindex=0,Bcnt=0;
memset(head,-1,sizeof(head));
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(num,0,sizeof(num));
memset(indegree,0,sizeof(indegree));
memset(maxans,0,sizeof(maxans));
for(i=0;i<=n;++i)
mp[i].clear();
}
void addEdge(int from,int to)
{
edge[tot].to=to;
edge[tot].next=head[from];
head[from]=tot++;
}
int Scan()
{
char ch;
int ret=0;
while((ch=getchar())<'0'||ch>'9');
while(ch>='0'&&ch<='9')
{
ret=ret*10+(ch-'0');
ch=getchar();
}
return ret;
}
void Tarjan(int x)
{
int i,u,v;
dfn[x]=low[x]=++Dindex;//时间戳
stack[top++]=x;
instack[x]=1;
for(i=head[x];i!=-1;i=edge[i].next)
{
u=edge[i].to;
if(!dfn[u])
{
Tarjan(u);
low[x]=low[x]>low[u]?low[u]:low[x];
}
else if(instack[u]&&low[x]>dfn[u])
low[x]=dfn[u];
}
if(low[x]==dfn[x])
{
//Bcnt++;
do
{
v=stack[--top];
instack[v]=0;
belong[v]=Bcnt;
num[Bcnt]++;//保存该强连通分量的点数
} while (v!=x);
Bcnt++;
}
}
void DFS(int x)
{
instack[x]=1;
tot+=num[x];
for(int i=0;i<mp[x].size();++i)
{
if(!instack[mp[x][i]])
DFS(mp[x][i]);
}
return ;
}
int main()
{
int m,test,i,j,x,Max,cases=1;
scanf("%d",&test);
while(test--)
{
n=Scan();
m=Scan();
Init(n);
while(m--)
{
i=Scan();
j=Scan();
// i++,j++;
addEdge(i,j);
}
for(i=0;i<n;++i)
{
if(!dfn[i])
Tarjan(i);
}
for(i=0;i<n;++i)
{
for(j=head[i];j!=-1;j=edge[j].next)
{
x=edge[j].to;
if(belong[i]!=belong[x]) //不在同一个连通分量的点
{
mp[belong[x]].push_back(belong[i]);
indegree[belong[i]]++;
}
}
}
Max=-1;
for(i=0;i<Bcnt;++i)
{
tot=0;
if(indegree[i]==0)
{
memset(instack,0,sizeof(instack));
DFS(i);
maxans[i]=tot;//保存每一个入度为0的最大值
Max=Max<tot?tot:Max;
}
}
printf("Case %d: %d\n",cases++,Max-1);
x=0;
for(i=0;i<n;++i)
{
if(maxans[belong[i]]==Max)
{
if(!x)
{
printf("%d",i);
x=1;
}
else
printf(" %d",i);
}
}
printf("\n");
}
return 0;
}