图的相关程序


//                      Author: sky
//			Date:  2011.11.4
//			Content: 图的相关程序
///

#include <iostream>
#include <string>
using namespace std;

#define  DEFAULT_SIZE 20
#define  DEFAULT_WEIGHT 0
bool visitable[DEFAULT_SIZE];// 标示节点是否被访问过
//
//   摔角选手goodguy 和badguy的分配问题
int color[DEFAULT_SIZE];//表示每个节点的颜色
enum{goodGuy=1,badGuy=2};
int colorFlag=goodGuy;
bool IsDesignFlag=true;
//
//打印两个点之间的线路(如果存在的话)
bool IsFind=false;
string Path="";// 记录所经过的线路


struct Graph	//本程序采用邻接矩阵方式存储图
{
	Graph();
	bool Initialize(int vNum,int eNum,string nStr,int graType);
	int GetVertexLoc(char a) const;//得到节点 在途中的标号 i
	bool InsertNode(char beginNode,char endNode,int edgWeight);
	bool IsAcylic();//判断一个图是否是有向无环图(采用拓扑排序的方法)
	string node;//记录节点的字母表示
	int weight[DEFAULT_SIZE][DEFAULT_SIZE];
	int vertexNum,edgeNum,graphType;//分别代表 顶点个数 边的个数以及图的类型(1表示无向 2表示有向)
};
void DFS(Graph gra,int k=-1);//深度优先遍历(递归方法)
void BFS(Graph gra);		//广度优先遍历

void IsDesign(Graph gra,int k=-1);//  实质是着色问题 即共两种颜色,图中相邻点不能为同一种颜色
//通过此函数判断能否着色成功
void PrintPath(Graph gra,char beginVertex,char endVertex);//k=-1表示 图中不存在该节点

Graph::Graph()
{
	node="";
	vertexNum=DEFAULT_SIZE;
	edgeNum=DEFAULT_SIZE;

}
bool Graph::Initialize(int vNum,int eNum,string nStr,int graType)
{
	if (nStr.length()!=vNum)
	{
		cout<<"The Number of Node must be"<<vNum;
		return false;
	}
	vertexNum=vNum;
	edgeNum=eNum;
	graphType=graType;
	node=nStr;
	for (int i=0;i<vertexNum;i++)
	{
		for (int j=0;j<vertexNum;j++)
		{
			weight[i][j]=DEFAULT_WEIGHT;//权重初始化为0  同时也可以表示两个顶点不可达
		}
		visitable[i]=false;//初始化访问节点 为false
	}
	return true;
}

int Graph::GetVertexLoc(char a)const
{
	for (int i=0;i<vertexNum;i++)
	{
		if (node[i]==a)
			return i;
	}
	return -1;
}

bool Graph::InsertNode(char beginNode,char endNode,int edgWeight)
{
	int i=GetVertexLoc(beginNode);
	int j=GetVertexLoc(endNode);
	if (i==-1||j==-1)
	{
		cout<<"Node is not in Graph"<<endl;
		return false;
	}
	weight[i][j]=edgWeight;//表示有向图
	if (graphType==1)
	{
		weight[j][i]=weight[i][j];//表示无向图
	}
	return true;
}

bool Graph::IsAcylic()//使用拓扑排序判断有向图是否存在环
{
	if (graphType!=2)//判断是否是有向图
	{
		return false;
	}
	bool checked[DEFAULT_SIZE];
	for (int i=0;i<vertexNum;i++)
	{
		checked[i]=false;
	}
	int inDegree=0;//inDegree 表示入度的个数
	for(int i=0;i<vertexNum;i++)
	{
		checked[i]=false;
		for (int j=0;j<vertexNum;j++)
		{
			if(weight[j][i]!=DEFAULT_WEIGHT&&(checked[i]==false)&&(checked[j]==false))
				inDegree++;
		}
		if (inDegree==0)
		{
			checked[i]=true;
		}
		inDegree=0;
	}
	for(int i=vertexNum-1;i>=0;i--)
	{
		for (int j=0;j<vertexNum;j++)
		{
			if(weight[j][i]!=DEFAULT_WEIGHT&&(checked[i]==false)&&(checked[j]==false))
				inDegree++;
		}
		if (inDegree==0)
		{
			checked[i]=true;
		}
		inDegree=0;
	}
	for(int i=0;i<vertexNum;i++)
	{
		if (checked[i]==false)
		{
			return false;//如果仍然存在没有被访问的点 说明存在环
		}
	}
	return true;
}

void DFS(Graph gra,int k)
{
	if(k==-1)//表示第一次执行 实质 是递归的最上层循环
	{
		for (int j=0;j<gra.vertexNum;j++)
		{
			if (!visitable[j])
			{
				DFS(gra,j);
			}
		}
	}
	else
	{
		cout<<gra.node[k]<<"	";//此处因为第一次执行的时候肯定visitable==false
		visitable[k]=true;
		for (int j=0;j<gra.vertexNum;j++)
		{
			bool judge=(gra.weight[k][j]!=DEFAULT_WEIGHT)&&(visitable[j]==false);
			if (judge)
			{
				DFS(gra,j);
			}
		}
	}

}

void BFS(Graph gra)
{
	for (int i=0;i<gra.vertexNum;i++)
	{
		if (!visitable[i])
		{
			cout<<gra.node[i]<<"	";
			visitable[i]=true;
			for (int j=0;j<gra.vertexNum;j++)
			{
				if ((gra.weight[i][j]!=DEFAULT_WEIGHT)&&(!visitable[j]))
				{
					cout<<gra.node[j]<<"	";
					visitable[j]=true;
				}
			}
		}
	}
}

void IsDesign(Graph gra,int k)//着色问题的核心函数
{

	if(k==-1)//表示第一次执行
	{
		bool aloneVertexFlag=false;
		for (int j=0;j<gra.vertexNum;j++)
		{
			if (visitable[j]==false)
			{
				IsDesign(gra,j);
			}
		}
	}
	else
	{
		visitable[k]=true;
		color[k]=colorFlag;

		for (int j=0;j<gra.vertexNum;j++)
		{
			if (gra.weight[k][j]!=DEFAULT_WEIGHT)
			{

				if (visitable[j]==false)
				{
					if (color[k]==goodGuy)//每遍历到一个节点之后 就改变一次colorFlag
					{
						colorFlag=badGuy;
					} 
					else
					{
						colorFlag=goodGuy;
					}
					IsDesign(gra,j);
				}
				else   //否则的话 就表示 两个点有连线 而且已经被访问过了,所以可以用来检测是否能涂色
				{
					if(color[k]==color[j])
					{
						IsDesignFlag=false;
					}
				}
			}
		}
	}
}
void PrintPath(Graph gra,char beginVertex,char endVertex)//查找路线的核心函数
{
	int k=gra.GetVertexLoc(beginVertex);//找到起始顶点 在邻接矩阵中的位置
	if (k==-1||(gra.GetVertexLoc(endVertex)==-1))
	{
		cout<<"illegal Vertex"<<endl;
		return;
	}
	visitable[k]=true;
	Path+=gra.node[k];
	Path+="-->";
	if(endVertex==gra.node[k])
	{
		IsFind=true;
		return;
	}
	for (int j=0;j<gra.vertexNum;j++)
	{
		if((gra.weight[k][j]!=DEFAULT_WEIGHT) &&(visitable[j]==false))
		{
			PrintPath(gra,gra.node[j],endVertex);
			if (IsFind==true)return;
		}
	}
	if (IsFind==false)//如果没找到 就取消线路上的节点
	{
		Path=Path.substr(0,Path.size()-4);
	}
}

void FirstProblem()//
{
	int verNum=0,edgNum=0,graType=1;
	string nodeStr;
	Graph gra;
	cout<<"\n\n\n\nInput Vertex Number: ";cin>>verNum;
	cout<<"Input Edge Number: "; cin>>edgNum;
	cout<<"Input Node String with no space(eg, ABCDEF): ";cin>>nodeStr;

	if(!gra.Initialize(verNum,edgNum,nodeStr,graType))
	{
		cout<<"Initialization error!";
		return ;
	}
	for (int i=0;i<edgNum;i++)
	{
		char a,b;
		int eweight=1;//此处设定了默认的权重为1 因为不涉及权重 固不输入权重
		cout<<"\nPlease Input edge "<<(i+1)<<" :";
		cin>>a>>b;
		if(!gra.InsertNode(a,b,eweight)) return;
	}

	IsDesign(gra);
	cout<<"\nIs possible to Design? The answer is :\n";
	if(IsDesignFlag)
	{
		cout<<"\t\t\tYes, you can get the answer like that"<<endl;
		for (int i=0;i<verNum;i++)
		{
			cout<<'\n\t'<<gra.node[i]<<" locates ";
			if (color[i]==1)
			{
				cout<<" goodGuy"<<endl;
			}
			else
			{
				cout<<" badGuy"<<endl;
			}
		}

	}
	else
	{
		cout<<"\n!No solution"<<endl;
	}
}
void SencondProblem()//
{
	int verNum=0,edgNum=0,graType=2;//2表示有向图
	string nodeStr;
	Graph gra;
	cout<<"\n\n\n\nInput Vertex Number: ";cin>>verNum;
	cout<<"Input Edge Number: "; cin>>edgNum;
	cout<<"Input Node String with no space(eg, ABCDEF): ";cin>>nodeStr;

	if(!gra.Initialize(verNum,edgNum,nodeStr,graType))
	{
		cout<<"Initialization error!";
		return ;
	}
	for (int i=0;i<edgNum;i++)
	{
		char a,b;
		int eweight=1;//此处设定了默认的权重为1 因为不涉及权重 固不输入权重
		cout<<"\nPlease Input edge "<<(i+1)<<" :";
		cin>>a>>b;
		if(!gra.InsertNode(a,b,eweight)) return ;
	}
	
	if(gra.IsAcylic()==false)//判断是否为有向无环图
	{
		cout<<" Sorry, This is not a directed acylic Graph ";
		return ;
	}
	char beginVertex,endVertex;
	cout<<"\n\nInput two Vertex: ";
	cin>>beginVertex>>endVertex;
	PrintPath(gra,beginVertex,endVertex);
	if (IsFind)
	{
		Path=Path.substr(0,Path.size()-3);
		cout<<"The Path is : "<<Path;
	}
	else
	{
		cout<<"\n!Sorry, Two Vertex can't communication";
	}
}
int main(int agrc,char* argv[])
{
	Graph gra=InputGraph();
	cout<<"Print by DFS:"<<endl;
	DFS(gra);

	cout<<"\nPrint by BFS:"<<endl;
	for(int i=0;i<gra.vertexNum;i++)
	visitable[i]=false;
	BFS(gra);
	cout<<"The first Problem :\n";
	FirstProblem();
	cout<<"The second Problem :\n";
	SencondProblem();
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值