图的强连通分量:即子图中的所有顶点都能够到当前子图中的任意其它顶点。
程序是参考的《算法导论》中图那一张的强连通分量一节。算法思想:先用DFS遍历一遍图,标记其discover时间和finish时间,然后用当前的图创建其转置图,即顶点相同,边的方向相反。然后按照转置图的finish时间从大到小一次遍历,得到的一个森林就是需要的强连通图。
代码:
//GraphMatrix.h
#ifndef __GraphMatrix__
#define __GraphMatrix__
#include<iostream>
#include<vector>
#include<list>
#include<stack>
#include<algorithm>
using namespace std;
struct Vertex
{
enum COL{WHITE,GRAY,BLACK};
char data;
int discover;
int finish;
COL color;
bool visited;
Vertex(char d=0)
{
data=d;
discover=0;
finish=0;
visited=false;
color=WHITE;
}
};
struct Edge
{
int weight;
Edge(int w=INT_MAX)
{
weight=w;
}
};
class GraphMatrix
{
int n;
int e;
vector<Vertex> V;//顶点集合
vector<vector<Edge> >E;//边的集合
void DFS(Vertex& v,int &time);
void DFS(Vertex& v,vector<Vertex> &);
public:
GraphMatrix()
{
n=e=0;
}
GraphMatrix(const GraphMatrix& g)//构造g的转置图,即顶点相同,边方向相反
{
n=e=0;
V=g.V;
vector<Edge> temp(V.size(),INT_MAX);
for(int i=0;i<V.size();i++)
E.push_back(temp);
for(int i=0;i<E.size();i++)
{
for(int j=0;j<E[0].size();j++)
{
if(g.E[i][j].weight!=INT_MAX)
{
E[j][i].weight=g.E[i][j].weight;
}
}
}
}
int insertVertex(Vertex & v);
void insertEdge(Vertex from,Vertex to,Edge e);
void removeEdge(Vertex from,Vertex to);
void removeVertex(Vertex &v);
void dfs(Vertex v);
vector<vector<Vertex> > dfs();
};
bool comp(Vertex &first,Vertex& second);
#endif
//GraphMatrix.cpp
#include"GraphMatrix.h"
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
void GraphMatrix::DFS(Vertex& v,int &time)
{
if(v.visited==true)
return ;
time++;
int k=-1;
for(int i=0;i<V.size();i++)
if(V[i].data==v.data)
{
k=i;
break;
}
if(k==-1)
return ;
if(V[k].visited==false)
{
V[k].visited=true;
V[k].color=Vertex::GRAY;
V[k].discover=time;
cout<<v.data<<endl;
}
for(int i=0;i<E[k].size();i++)
{
if(E[k][i].weight!=INT_MAX && V[i].visited==false)
DFS(V[i],time);
}
time++;
V[k].finish=time;
}
int GraphMatrix::insertVertex(Vertex & v)
{
V.push_back(v);
E.push_back(vector<Edge>(V.size()));
if(E.size()>1)
for(int i=0;i<V.size()-1;i++)
E[i].push_back(Edge());
n++;
return V.size()-1;
}
void GraphMatrix::insertEdge(Vertex from,Vertex to,Edge e)
{
int k=0;
int p=-1,q=-1;
for(int i=0;i<V.size();i++)
{
if(V[i].data==from.data)
{
k+=1;
p=i;
}
if(V[i].data==to.data)
{
k+=2;
q=i;
}
}
if((k&1)==0)
p=insertVertex(from);
if((k&2)==0)
q=insertVertex(to);
E[p][q]=e;
// E[q][p]=e;//如果不屏蔽则是无向图
this->e++;
}
void GraphMatrix::removeEdge(Vertex from,Vertex to)
{
int k=0;
int p=-1,q=-1;
for(int i=0;i<V.size();i++)
{
if(V[i].data==from.data)
p=i;
if(V[i].data==to.data)
q=i;
}
if(p==-1 || q==-1)
return ;
else
E[p][q]=INT_MAX;
n--;
}
void GraphMatrix::removeVertex(Vertex &v)
{
int k=-1;
for(int i=0;i<V.size();i++)
{
if(V[i].data==v.data)
k=i;
}
if(k==-1)
return ;
V.erase(V.begin()+k);
for(int i=0;i<E.size();i++)
E[i].erase(E[i].begin()+k);
E.erase(E.begin()+k);
n--;
}
void GraphMatrix::dfs(Vertex v)
{
for(int i=0;i<V.size();i++)
V[i].visited=false;
int time=0;
DFS(v,time);
for(int i=0;i<V.size();i++)
if(V[i].visited==false)
DFS(V[i],time);
}
/**/
vector<vector<Vertex> > GraphMatrix::dfs()
{
for(int i=0;i<V.size();i++)
V[i].visited=false;
vector<vector<Vertex> >result;
vector<Vertex> temp=V;
sort(temp.begin(),temp.end(),comp);
for(int i=0;i<V.size();i++)
{
for(int j=0;j<V.size();j++)
{
if(V[j].data==temp[i].data && V[j].visited==false)
{
vector<Vertex> r;
DFS(V[j],r);
result.push_back(r);
}
}
}
return result;
}
void GraphMatrix::DFS(Vertex& v,vector<Vertex> &r)
{
if(v.visited==true)
return ;
int k=-1;
for(int i=0;i<V.size();i++)
if(V[i].data==v.data)
{
k=i;
break;
}
if(k==-1)
return ;
if(V[k].visited==false)
{
V[k].visited=true;
r.push_back(V[k]);
cout<<v.data<<endl;
}
for(int i=0;i<E[k].size();i++)
{
if(E[k][i].weight!=INT_MAX && V[i].visited==false)
DFS(V[i],r);
}
}
bool comp(Vertex &first,Vertex& second)
{
return first.finish>second.finish;
}
#include<iostream>
#include"GraphMatrix.h"
using namespace std;
#define DEBUG
int main()
{
#ifdef DEBUG
freopen("input.txt","r",stdin);
#endif
GraphMatrix gm;
char from,to;
int e;
//测试边和顶点的插入
cout<<"输入边"<<endl;
while(cin>>from>>to>>e)
{
cout<<"输入边"<<endl;
gm.insertEdge(from,to,e);//调用默认构造函数
}
//深度优先搜索
gm.dfs('A');
GraphMatrix gmT(gm);
vector<vector<Vertex> >result=gmT.dfs();//result中每行表示一个强连通分量
system("pause");
return 0;
}
输入:input.txt文件的内容为:
A C 0
B C 0
C D 0
D A 0
C E 0
C F 0
E F 0
最后result的内容为:[B],[A,D,C],[E],[F]。和输入的图完全匹配