#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#define MAXN 5010
using namespace std;
vector<int> g[MAXN],g2[MAXN];//g保存原圖,g2保存縮點反向後的圖
stack<int> st;
int n,index,num,dfn[MAXN],low[MAXN],f[MAXN];
bool vis[MAXN],instack[MAXN];
int ans[MAXN],in[MAXN],scc[MAXN],sum;
void tarjan(int u)//求強連通分支
{
int v;
dfn[u] = low[u] = index++;
st.push(u);
instack[u] = true;
vis[u] = true;
for(int i=0; i<g[u].size(); i++)
{
v = g[u][i];
if(!vis[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u])
{
do
{
v = st.top();
instack[v] = false;
st.pop();
f[v]=num;//記錄每一個點所在的強連通分支
scc[num]++;//保存該強連通分支的點數
}
while(v != u);
num++;
}
}
void dfs(int u)//深搜求出可到達該連通分支的點數
{
vis[u]=true;
sum+=scc[u];
for(int i=0;i<g2[u].size();i++)
if(!vis[g2[u][i]])
dfs(g2[u][i]);
}
int main()
{
int T,m,a,b,cas=0;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
for(int i=0;i<=n;i++)//注意要將向量清空
{
g[i].clear();
g2[i].clear();
}
while(m--)
{
scanf("%d %d",&a,&b);
g[a].push_back(b);
}
index=num=0;
memset(vis,false,sizeof(vis));
memset(instack,false,sizeof(instack));
memset(scc,0,sizeof(scc));
for(int i=0;i<n;i++)
{
if(!vis[i])
tarjan(i);
}
memset(in,0,sizeof(in));
for(int i=0;i<n;i++)//重新構圖
for(int j=0;j<g[i].size();j++)
{
if(f[i]!=f[g[i][j]])
{
g2[f[g[i][j]]].push_back(f[i]);
in[f[i]]++;
}
}
int maxans=-1;
memset(ans,-1,sizeof(ans));
printf("Case %d: ",++cas);
for(int i=0;i<num;i++)
{
if(in[i]==0)
{
sum=0;
memset(vis,false,sizeof(vis));
dfs(i);
ans[i]=sum;
if(sum>maxans)
maxans=sum;
}
}
printf("%d\n",maxans-1);
int flag=0;
for (int i = 0; i < n; i++)
if ( ans[f[i]] == maxans)
{
if(!flag){
printf("%d", i);
flag=1;
}
else printf(" %d",i);
}
printf("\n");
}
return 0;
}
tjut 3639
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.