这个算法可以解决判断和打印各个强连通分量的问题。对于本题,只要判断就行。
#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;
}