這個算法可以解決判斷和打印各個強連通分量的問題。對於本題,只要判斷就行。
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
const int MAXV=11000;
vector<int>G[MAXV],T_G[MAXV]; //原圖和轉置圖
vector<int>S; //用來存放dfs後的各點離開時間
int vis[MAXV],sccno[MAXV],scc_cnt;
//vis標記,sccno記錄各點屬於哪個強連通分量,scc_cnt記錄分量個數
void dfs(int u)
{
if(vis[u])return ;
vis[u]=1; //標記
for(int i=0; i<G[u].size(); i++)
{
dfs(G[u][i]);
}
S.push_back(u);
}
void T_dfs(int u)
{
if(sccno[u])return ;
sccno[u]=scc_cnt; //u爲該分量的一個點
for(int i=0; i<T_G[u].size(); i++)
{
T_dfs(T_G[u][i]); //深搜該點
}
}
int find_scc(int n)
{
scc_cnt=0;
S.clear();
memset(vis,0,sizeof(vis));
memset(sccno,0,sizeof(sccno));
for(int i=1; i<=n; i++) //深搜1-n每個節點
{
dfs(i);
}
for(int i=n-1; i>=0; i--) //搜索由晚到早離開的點
{
if(!sccno[S[i]])
{
scc_cnt++; //分量個數增加
T_dfs(S[i]);
}
}
for(int i=1; i<=n; i++)
{
G[i].clear();
T_G[i].clear();
}
return scc_cnt;
}
void Transform(int n,vector<int>*Graph) //將圖轉置
{
for(int i=1; i<=n; i++)
{
for(int j=0; j<Graph[i].size(); j++)
{
T_G[Graph[i][j]].push_back(i);
}
}
}
bool kosaraju(int n)
{
if(find_scc(n)==1)
return true;
return false;
}
int main()
{
int n,m,a,b;
while(scanf("%d%d",&n,&m)!=EOF&&(n+m))
{
for(int i=0; i<m; i++)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
}
Transform(n,G);
if(kosaraju(n))
printf("Yes\n");
else
printf("No\n");
/* for(int i=1;i<=scc_cnt;i++){
//scc_cnt表示強連通分量個數
for(int j=1;j<=n;j++){ //遍歷所有點
if(sccno[j]==i)
//如果該點在同一個強連通分量中輸出
printf("%d ",j);
}
printf("\n");
}*/
}
return 0;
}