Kosaraju算法
题目
思路:建一个反图,从最后的强连通分量遍历。如果所有点都被访问过了,那么最后一个强连通分量中点的个数就是答案,否则没有。
#include<bits/stdc++.h>
using namespace std;
#define maxn 10010
int m,n,nl,mmp,sum,cmp[maxn];
vector<int> g[maxn],rg[maxn],vs;
bool used[maxn];
void add(int a,int b){
g[a].push_back(b);
rg[b].push_back(a);//反图
}
void dfs(int v) {
used[v]=1;
for(int i=0;i<g[v].size();i++){
if(!used[g[v][i]])
dfs(g[v][i]);
}
vs.push_back(v);
}//没有访问过就搜索,然后压入vs
void rdfs(int v,int k){
used[v]=1;
cmp[v]=k;
for(int i=0;i<rg[v].size();i++){
if(!used[rg[v][i]])
rdfs(rg[v][i],k);
}
}
int scc(){
memset(used,0,sizeof(used));
vs.clear();
for(int i=1;i<=n;i++)
if(!used[i])
dfs(i);
memset(used,0,sizeof(used));
int k=0;
for(int i=vs.size()-1;i>=0;i--)
if(!used[vs[i]])
rdfs(vs[i],k++);
return k;
}//k为强连通分量个数
int main(){
int u,p;
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>u>>p,add(u,p);
int ans=scc();
for(int i=1;i<=n;i++)
if(cmp[i]==ans-1){
mmp=i;
sum++;
}
memset(used,0,sizeof(used));
rdfs(mmp,1);
for(int i=1;i<=n;i++)
if(!used[i]){
cout<<0<<endl;
return 0;
}
cout<<sum<<endl;
return 0;
}