//有向图的强连通分量
/*
强连通分量
再一个强连通分量中,任何两点都可达
将所有的强连通分量看作一个点
得到的所有有向图一定是DAG(有向无环图)
如果存在环的话,那么这个环上的节点必然能够组成强连通分量
*/
#include<vector>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<fstream>
#include<set>
#include<map>
using namespace std;
typedef struct VNode{
int indegree, outdegree;
VNode(){
indegree = 0;
outdegree = 0;
}
set<int> st;//map key 是节点号,即该节点到key之间有一条边,权重是value
}VN;
typedef struct Graph{
int v,e;
VN* ag;
}G;
void initG(G* g, G* rg);
void DFS(G* g, int v, int flag);
void Kosaraju(G* g, G* rg);
int* visited;
int scccount = 0;
vector<int> ve;
int main(){
G* g = new G;
G* rg = new G;
initG(g, rg);
Kosaraju(g, rg);
cout<<scccount;
return 0;
}
void initG(G* g, G* rg){
ifstream infile;//输入流
infile.open("data.txt",ios::in);
if(!infile.is_open()){
cout << "Flie open failure" <<endl;
return;
}
infile >> g->v >> g->e ;
rg->v = g->v;
rg->e = g->e;
g->ag = new VN[g->v];
rg->ag = new VN[rg->v];
visited = new int[g->v];
fill(visited, visited+g->v, 0);
//Input the edge and weight
for(int i = 0; i < g->e; i++){
int node1, node2;
infile >> node1 >> node2;
g->ag[node1].st.insert(node2); //有向图
rg->ag[node2].st.insert(node1); //反图
}
infile.close();
}
void DFS(G* g, int v, int flag){
visited[v] = flag;
set<int>::iterator it = g->ag[v].st.begin();
for(; it != g->ag[v].st.end(); it++){
if(visited[*it] == 0){
DFS(g,*it,flag);
}
}
ve.push_back(v);
}
void Kosaraju(G* g, G* rg){
for(int i = 0; i < g->v; i++){
if(visited[i] == 0){
DFS(g,i,1);
}
}
reverse(ve.begin(),ve.end());//逆序伪拓扑排序
fill(visited,visited+g->v, 0);
int flag = 0;
for(int i = 0; i < ve.size(); i++){
if(visited[ve[i]] == 0){
flag++;
DFS(rg,ve[i],flag);//传入的rg,反图
}
}
scccount = flag;
}
Kosaraju算法
最新推荐文章于 2024-03-24 10:19:34 发布