问答题 设G是一个用邻接表表示的连通无向图。对于G中某个顶点v,若从G中删去顶点v及与顶点v相关联的边后,G变成由两个或两个以上非空连通分量所组成的图,则称v是原来图G的一个关节顶点。如下图中,只有顶点4和顶点6是关节顶点,而其他顶点都不是关节顶点。试叙述寻找图G的所有关节顶点的算法,并用算法语言(Pascal或C)编写一个实现你所给出的算法的程序。【复旦大学1996八(20分)】
【正确答案】正确答案:由关节顶点定义及特性可知,若生成树的根有多于或等于两棵子树,则根结点是关节顶点;若生成树某非叶子顶点v,其子树中的结点没有指向v的祖先的回边,则v是关节顶点。因此,对图G=(v,{Edge}),将访问函数visitedM定义为深度优先遍历连通图时访问顶点v的次序号,并定义一个low()函数:low(v)一Min(visited[v],low[w],Visited[k])其中(v,w)∈Edge,(v,k)∈Edge,w是v在深度优先生成树上的孩子结点,k是v在深度优先生成树上的祖先结点。在如上定义下,若low[w]≥visited[v],则v是根结点,因w及其子孙无指向v的祖先的回边。由此,一次深度优先遍历连通图,就可求得所有关节顶点。 int visited[],low[]; //访问函数visited和low函数为全局变量 int count; //记访问顶点个数 AdjListg; //图g以邻接表方式存储 void dfs articul(vertype v0) //深度优先遍历求关节顶点 fcount++;visited[v0]_courlt; //访问顶点顺序号放入visited min=visited [v0]; //初始化访问初值 p=g Iv0].firstarc; //求顶点v的邻接点 while(p!=null) {w=p一>adjvex; //顶点v的邻接点 if(visited[w]==0)llw未曾访问,W是v0的孩子 {dfs articul(g,w); if(low[w]=visited Iv0])printf(g Iv0].vertex);//vo是关节顶点 }//if else //w已被访问,是v的祖先 if(visited[w]next; }//while low[v0]=min; } //结束dfs articul void get—articul() //求以邻接表为存储结构的无向连通图g的关结点 {for(vi=1;vi<=n;vi++)visited[vi]=0;//图有n个顶点,访问数组初始化 count=1;visited[1]=1; //设邻接表上第一个顶点是生成树的根 p=g[1].firstarc; v=p一>adjvex; dfs—articul(v); if(countnext!=null) {p=p->next;V=p一>adjVex;if(visited Iv]==0)dfs-articul(v);)//while } } //结束get—articul
【答案解析】