题目大意简单:注意,如果1->2,2->3,3->1,,则最大支持为2,
运行tarjan将强连通分量缩点,形成一个DAG, 对DAG建立反图,那么为入度为0的点,才可能为有最大支持量(或正向建图,出度为0的点),所以对入度为0的点bfs即可求出最大的支持量,有些细节要注意具体见代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct node
{
int u,v;
};
node e[40000];
int first[5005],next[40000];
int dfn[5005],low[5005],flag[5005],stack[5005];
int cc,time,top,sum;
int num[5005],vis[5005];
int first1[5005],next1[40000],inde[5005];
node e1[40000];
int temp[5004];
inline void add_edge(int u,int v)
{
e[cc].u=u;
e[cc].v=v;
next[cc]=first[u];
first[u]=cc;
cc++;
}
inline void add_edge1(int u,int v)
{
e1[cc].u=u;
e1[cc].v=v;
next1[cc]=first1[u];
first1[u]=cc;
cc++;
}
int tardfs(int s)
{
flag[s]=1;
stack[++top]=s;
low[s]=dfn[s]=time++;
int i;
for(i=first[s];i!=-1;i=next[i])
{
int v=e[i].v;
if(flag[v]==0)
tardfs(v);
if(flag[v]==1)
low[s]=min(low[s],low[v]);
}
if(low[s]==dfn[s])
{
sum++;
do
{
low[stack[top]]=sum;
flag[stack[top]]=2;
num[sum]++;
}while(stack[top--]!=s);
}
return 0;
}
int tarjan(int n)
{
memset(flag,0,sizeof(flag));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(num,0,sizeof(num));
int i;
time =1;
top=0;
sum=0;
for(i=0;i<n;i++)
{
if(flag[i]==0)
tardfs(i);
}
return 0;
}
int bfs(int i)
{
queue<int> q;
int sum=num[i]-1;
q.push(i);
memset(vis,0,sizeof(vis));
vis[i]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
int j;
for(j=first1[u];j!=-1;j=next1[j])
{
if(!vis[e1[j].v])
{
vis[e1[j].v]=1;
sum+=num[e1[j].v];
q.push(e1[j].v);
}
}
}
return sum;
}
int main()
{
int tt,cas;
scanf("%d",&tt);
for(cas=1;cas<=tt;cas++)
{
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
int n,m;
scanf("%d%d",&n,&m);
int i;
cc=0;
for(i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
tarjan(n);
cc=0;
memset(first1,-1,sizeof(first1));
memset(next1,-1,sizeof(next1));
memset(inde,0,sizeof(inde));
for(i=0;i<n;i++)
{
int j;
for(j=first[i];j!=-1;j=next[j])
if(low[e[j].u]!=low[e[j].v])
{
add_edge1(low[e[j].v],low[e[j].u]);
inde[low[e[j].u]]++;
}
}
int res=0;
memset(temp,0,sizeof(temp));
for(i=1;i<=sum;i++)
{
if(inde[i]==0)
{
int ans=bfs(i);
temp[i]=ans;
if(ans>res)
{
res=ans;
}
}
}
printf("Case %d: %d\n",cas,res);
int ff=0;
for(i=0;i<n;i++)
{
if(temp[low[i]]==res)
{
if(ff==0)
printf("%d",i),ff=1;
else
printf(" %d",i);
}
}
printf("\n");
}
return 0;
}