tjut 3639

#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; 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章