网易有道笔试:求连通图的割点(关节点)

http://blog.csdn.net/cxllyg/article/details/7610265

题目:求一个连通图的割点,割点的定义是,如果除去此节点和与其相关的边,图不再连通,描述算法。

分析:

1. 最简单也是最直接的算法是,删除一个点然后判断连通性,如果删除此点,图不再连通,则此点是割点,反之不是割点(图的连通性一般通过深搜来判定,是否能一次搜索完 全部顶点);

2. 通过深搜优先生成树来判定。从任一点出发深度优先遍历得到优先生成树,对于树中任一顶点V而言,其孩子节点为邻接点。由深度优先生成树可得出两类割点的特性:

     (1)若生成树的根有两棵或两棵以上的子树,则此根顶点必为割点。因为图中不存在连接不同子树顶点的边,若删除此节点,则树便成为森林;

     (2)若生成树中某个非叶子顶点V,其某棵子树的根和子树中的其他节点均没有指向V的祖先的回边,则V为割点。因为删去v,则其子树和图的其它部分被分割开来。

仍然利用深搜算法,只不过在这里定义visited[v]表示为深度优先搜索遍历图时访问顶点v的次序号,定义low[v]=Min{visited[v],low[w],visited[k]},其中w是顶点v在深度优先生成树上的孩子节点;k是顶点v在深度优先生成树上由回边联结的祖先节点。

   割点判定条件:如果对于某个顶点v,存在孩子节点w且low[w]>=visited[v],则该顶点v必为关节点。因为当w是v的孩子节点时,low[w]>=visited[v],表明w及其子孙均无指向v的祖先的回边,那么当删除顶点v后,v的孩子节点将于其他节点被分割开来,从来形成新的连通分量。

  1. #include <iostream>   
  2. #include <string>   
  3. using namespace std;  
  4.   
  5. #define MAX_VERTEX_NUM 13   
  6.   
  7. //邻接表存储结构   
  8. typedef struct ArcNode{  
  9.     int adjvex;  
  10.     ArcNode *nextarc;  
  11. }ArcNode;  
  12.   
  13. typedef struct VNode{  
  14.     string data;  
  15.     ArcNode* firstarc;  
  16. }VNode,AdjList[MAX_VERTEX_NUM];  
  17.   
  18. typedef struct{  
  19.     AdjList vertices;  
  20.     int vexnum, arcnum;  
  21. }ALGraph;  
  22.   
  23. //返回u在图中的位置   
  24. int LocateVex(ALGraph G, string u)  
  25. {  
  26.     for(int i=0; i<G.vexnum; i++)  
  27.         if(G.vertices[i].data==u)  
  28.             return i;  
  29.     return -1;  
  30. }  
  31.   
  32. //构造图   
  33. void CreateDG(ALGraph &G)  
  34. {  
  35.     string v1, v2;  
  36.     int i, j, k;  
  37.     cout<<"请输入顶点数和边数:";  
  38.     cin>>G.vexnum>>G.arcnum;  
  39.   
  40.     cout<<"请输入顶点:";  
  41.     for(i=0; i<G.vexnum; i++)  
  42.     {  
  43.         cin>>G.vertices[i].data;  
  44.         G.vertices[i].firstarc=NULL;  
  45.     }  
  46.   
  47.     cout<<"请输入边:"<<endl;  
  48.     for(k=0; k<G.arcnum; k++)  
  49.     {  
  50.         cin>>v1>>v2;  
  51.         i=LocateVex(G, v1);  
  52.         j=LocateVex(G, v2);  
  53.   
  54.         //无向图   
  55.         ArcNode *arc=new ArcNode;  
  56.         arc->adjvex=j;  
  57.         arc->nextarc=G.vertices[i].firstarc;  
  58.         G.vertices[i].firstarc=arc;  
  59.   
  60.         arc=new ArcNode;  
  61.         arc->adjvex=i;  
  62.         arc->nextarc=G.vertices[j].firstarc;  
  63.         G.vertices[j].firstarc=arc;  
  64.     }  
  65.   
  66. }  
  67.   
  68. //求割点   
  69. int count ;  
  70. int visited[MAX_VERTEX_NUM];  
  71. int low[MAX_VERTEX_NUM];  
  72.   
  73. //从第v0个顶点出发深搜,查找并输出关节点(割点)   
  74. void DFSArticul(ALGraph G, int v0)  
  75. {  
  76.     int min, w;  
  77.     ArcNode *p;  
  78.     visited[v0]=min=++count;//v0是第count个访问的顶点,min的初值为visited[v0],即v0的访问次序   
  79.   
  80.     for(p=G.vertices[v0].firstarc; p ; p=p->nextarc)  
  81.     {  
  82.         w=p->adjvex;  
  83.         if(visited[w]==0)//w未曾访问,是v0的孩子   
  84.         {  
  85.             DFSArticul(G, w);//从第w个顶点出发深搜,查找并输出关节点(割点),返回前求得low[w]   
  86.             if(low[w]<min)//如果v0的孩子节点w的low[]小,说明孩子节点还与其他节点(祖先)相邻   
  87.                 min=low[w];  
  88.             if(low[w]>=visited[v0])//v0的孩子节点w只与v0相连,则v0是关节点(割点)   
  89.                 cout<<G.vertices[v0].data<<" ";  
  90.         }  
  91.         else if(visited[w]<min)//w已访问,则w是v0生成树上祖先,它的访问顺序必小于min   
  92.             min=visited[w];  
  93.     }  
  94.   
  95.     low[v0]=min;//low[v0]取三者最小值   
  96.       
  97. }  
  98.   
  99. void FindArticul(ALGraph G)  
  100. {  
  101.     int i, v;  
  102.     ArcNode *p;  
  103.     count=1;  
  104.     visited[0]=1;//从0号节点开始   
  105.     for(i=1; i<G.vexnum; i++)  
  106.         visited[i]=0;  
  107.     p=G.vertices[0].firstarc;  
  108.     v=p->adjvex;  
  109.     DFSArticul(G, v);  
  110.     if(count<G.vexnum)  
  111.     {  
  112.         cout<<G.vertices[0].data<<" ";  
  113.         while(p->nextarc)  
  114.         {  
  115.             p=p->nextarc;  
  116.             v=p->adjvex;  
  117.             if(visited[v]==0)  
  118.                 DFSArticul(G, v);  
  119.         }  
  120.     }  
  121. }  
  122.   
  123. void main()  
  124. {  
  125.     ALGraph g;  
  126.     CreateDG(g);  
  127.   
  128.     cout<<"割点如下: "<<endl;  
  129.     FindArticul(g);  
  130.     cout<<endl;  
  131. }  
#include <iostream>
#include <string>
using namespace std;

#define MAX_VERTEX_NUM 13

//邻接表存储结构
typedef struct ArcNode{
	int adjvex;
	ArcNode *nextarc;
}ArcNode;

typedef struct VNode{
	string data;
	ArcNode* firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];

typedef struct{
	AdjList vertices;
	int vexnum, arcnum;
}ALGraph;

//返回u在图中的位置
int LocateVex(ALGraph G, string u)
{
	for(int i=0; i<G.vexnum; i++)
		if(G.vertices[i].data==u)
			return i;
	return -1;
}

//构造图
void CreateDG(ALGraph &G)
{
	string v1, v2;
	int i, j, k;
	cout<<"请输入顶点数和边数:";
	cin>>G.vexnum>>G.arcnum;

	cout<<"请输入顶点:";
	for(i=0; i<G.vexnum; i++)
	{
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	}

	cout<<"请输入边:"<<endl;
	for(k=0; k<G.arcnum; k++)
	{
		cin>>v1>>v2;
		i=LocateVex(G, v1);
		j=LocateVex(G, v2);

		//无向图
		ArcNode *arc=new ArcNode;
		arc->adjvex=j;
		arc->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=arc;

		arc=new ArcNode;
		arc->adjvex=i;
		arc->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=arc;
	}

}

//求割点
int count ;
int visited[MAX_VERTEX_NUM];
int low[MAX_VERTEX_NUM];

//从第v0个顶点出发深搜,查找并输出关节点(割点)
void DFSArticul(ALGraph G, int v0)
{
	int min, w;
	ArcNode *p;
	visited[v0]=min=++count;//v0是第count个访问的顶点,min的初值为visited[v0],即v0的访问次序

	for(p=G.vertices[v0].firstarc; p ; p=p->nextarc)
	{
		w=p->adjvex;
		if(visited[w]==0)//w未曾访问,是v0的孩子
		{
			DFSArticul(G, w);//从第w个顶点出发深搜,查找并输出关节点(割点),返回前求得low[w]
			if(low[w]<min)//如果v0的孩子节点w的low[]小,说明孩子节点还与其他节点(祖先)相邻
				min=low[w];
			if(low[w]>=visited[v0])//v0的孩子节点w只与v0相连,则v0是关节点(割点)
				cout<<G.vertices[v0].data<<" ";
		}
		else if(visited[w]<min)//w已访问,则w是v0生成树上祖先,它的访问顺序必小于min
			min=visited[w];
	}

	low[v0]=min;//low[v0]取三者最小值
	
}

void FindArticul(ALGraph G)
{
	int i, v;
	ArcNode *p;
	count=1;
	visited[0]=1;//从0号节点开始
	for(i=1; i<G.vexnum; i++)
		visited[i]=0;
	p=G.vertices[0].firstarc;
	v=p->adjvex;
	DFSArticul(G, v);
	if(count<G.vexnum)
	{
		cout<<G.vertices[0].data<<" ";
		while(p->nextarc)
		{
			p=p->nextarc;
			v=p->adjvex;
			if(visited[v]==0)
				DFSArticul(G, v);
		}
	}
}

void main()
{
	ALGraph g;
	CreateDG(g);

	cout<<"割点如下: "<<endl;
	FindArticul(g);
	cout<<endl;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值