图的强连通分量

图的强连通分量:即子图中的所有顶点都能够到当前子图中的任意其它顶点。

程序是参考的《算法导论》中图那一张的强连通分量一节。算法思想:先用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]。和输入的图完全匹配

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值