网易笔试题-求有向连通图的割点

来源:互联网 发布:淘宝虚拟商品物流 编辑:程序博客网 时间:2024/05/28 18:44

首先,明白割点定义:如果去除此点,则有向图不再连通。割点的具体情况可以结合下面的图来分析:


可以看到,割点有两种情况(通过深度优先搜索树来遍历):

1.如果是根节点,且有大于或等于两个以上的子树,则为割点。

2.如果不是叶节点的某节点node(比如节点J,K是叶子节点,但他们不属于割点),对于node来说它的子结点及后继结点没有指向node的祖先的回边,则为割点。譬如图中的E结点,它不满足这个条件所以为割点。

在具体实现的时候用visit[]数组来存储结点的访问顺序,而用low[]数组来存储结点能访问到的最小的结点顺序号。假设对于结点node来说,如果它的后继结点的low[]不小于visit[node]的话,则为割点。程序如下所示:

#include <iostream>#include <string>using namespace std;#define  MAX_NUM 20int visit[MAX_NUM] = {0};//存储结点的访问顺序int cuts[MAX_NUM]  = {0};//存储割点的数组int low[MAX_NUM];//记录每个顶点能访问的最先结点//邻接表struct Node{int num;Node* next;};struct vNode{string name;Node* firstarc;};struct Graph{vNode vnode[MAX_NUM];int nodenum,arcnum;};//根据值返回结点编号int LocateNode(Graph G,string data){for(int i =0;i<G.nodenum;i++){if(G.vnode[i].name == data)return i;}return -1;}void CreateGraph(Graph &G){string v1,v2;int i,j,k;cout<<"请输入顶点数和边数"<<endl;cin>>G.nodenum>>G.arcnum;cout<<"请输入顶点"<<endl;for(int i=0;i<G.nodenum;i++){cin>>G.vnode[i].name;G.vnode[i].firstarc = NULL;}cout<<"请输入边"<<endl;for(k=0;k<G.arcnum;k++){cin>>v1>>v2;i = LocateNode(G,v1);j = LocateNode(G,v2);//有向图Node* newnode = new Node;newnode->num = j;newnode->next= G.vnode[i].firstarc;G.vnode[i].firstarc = newnode;}}void DfstheG(Graph G,int v,int& count){int min,nodenum;count++;visit[v] = min = count;Node *p;for(p = G.vnode[v].firstarc;p;p=p->next){nodenum = p->num;if(visit[nodenum] == 0){DfstheG(G,nodenum,count);if(low[nodenum] < min)min = low[nodenum];//存在则为割点if(low[nodenum] >= visit[v])cuts[v] =1;}//已访问,则为v的祖先else if(visit[nodenum] < min){min = visit[nodenum];}}low[v] = min;}void FindGedian(Graph G){int count = 0;for(int i =0;i<G.nodenum;i++){if(visit[i] == 0)DfstheG(G,i,count);}cout<<"cuts nodes are:"<<endl;for(int i =0;i<G.nodenum;i++){if(cuts[i] == 1)cout<<G.vnode[i].name<<endl;}}int main(){Graph G;CreateGraph(G);FindGedian(G);system("PAUSE");return 0;}
测试结果如下图:


注意到去掉H点貌似是联通的。。这是为啥?求解答


原创粉丝点击