求一个连通图的割点(去掉一个点后图不再连通)
題目:求一個(gè)連通圖的割點(diǎn),割點(diǎn)的定義是,如果除去此節(jié)點(diǎn)和與其相關(guān)的邊,圖不再連通,描述算法。
分析:
1. 最簡(jiǎn)單也是最直接的算法是,刪除一個(gè)點(diǎn)然后判斷連通性,如果刪除此點(diǎn),圖不再連通,則此點(diǎn)是割點(diǎn),反之不是割點(diǎn)(圖的連通性一般通過(guò)深搜來(lái)判定,是否能一次搜索完 全部頂點(diǎn));
2. 通過(guò)深搜優(yōu)先生成樹(shù)來(lái)判定。從任一點(diǎn)出發(fā)深度優(yōu)先遍歷得到優(yōu)先生成樹(shù),對(duì)于樹(shù)中任一頂點(diǎn)V而言,其孩子節(jié)點(diǎn)為鄰接點(diǎn)。由深度優(yōu)先生成樹(shù)可得出兩類割點(diǎn)的特性:
???? (1)若生成樹(shù)的根有兩棵或兩棵以上的子樹(shù),則此根頂點(diǎn)必為割點(diǎn)。因?yàn)閳D中不存在連接不同子樹(shù)頂點(diǎn)的邊,若刪除此節(jié)點(diǎn),則樹(shù)便成為森林;
???? (2)若生成樹(shù)中某個(gè)非葉子頂點(diǎn)V,其某棵子樹(shù)的根和子樹(shù)中的其他節(jié)點(diǎn)均沒(méi)有指向V的祖先的回邊,則V為割點(diǎn)。因?yàn)閯h去v,則其子樹(shù)和圖的其它部分被分割開(kāi)來(lái)。
仍然利用深搜算法,只不過(guò)在這里定義visited[v]表示為深度優(yōu)先搜索遍歷圖時(shí)訪問(wèn)頂點(diǎn)v的次序號(hào),定義low[v]=Min{visited[v],low[w],visited[k]},其中w是頂點(diǎn)v在深度優(yōu)先生成樹(shù)上的孩子節(jié)點(diǎn);k是頂點(diǎn)v在深度優(yōu)先生成樹(shù)上由回邊聯(lián)結(jié)的祖先節(jié)點(diǎn)。
?? 割點(diǎn)判定條件:如果對(duì)于某個(gè)頂點(diǎn)v,存在孩子節(jié)點(diǎn)w且low[w]>=visited[v],則該頂點(diǎn)v必為關(guān)節(jié)點(diǎn)。因?yàn)楫?dāng)w是v的孩子節(jié)點(diǎn)時(shí),low[w]>=visited[v],表明w及其子孫均無(wú)指向v的祖先的回邊,那么當(dāng)刪除頂點(diǎn)v后,v的孩子節(jié)點(diǎn)將于其他節(jié)點(diǎn)被分割開(kāi)來(lái),從來(lái)形成新的連通分量。
#include <iostream> #include <string> #include <queue> using namespace std; #define MAXN 100 struct ArcNode { int adjVertex; //邊到的頂點(diǎn) ArcNode *next; }; struct VNode { string data; ArcNode *firstArc; }; typedef VNode AdjList[MAXN]; struct Graph { int vertexNum; int arcNum; AdjList vertexs; }; int Locate(Graph g,string str) { for(int i = 0;i<g.vertexNum;i++) { if(str == g.vertexs[i].data) return i; } return -1; } void Create(Graph &g) { string start,end; cout << "請(qǐng)輸入頂點(diǎn)和邊數(shù):"<<endl; cin>>g.vertexNum>>g.arcNum; for(int i = 0;i<g.vertexNum;i++) { cout<<"請(qǐng)輸入第"<<i<<"個(gè)頂點(diǎn):"<<endl; cin>>g.vertexs[i].data; g.vertexs[i].firstArc = NULL; } for(int i = 0;i <g.arcNum;i++) { cout<<"請(qǐng)輸入第"<<i<<"條邊的起始和結(jié)束頂點(diǎn)"<<endl; cin>>start>>end; int m = Locate(g,start); int n = Locate(g,end); ArcNode *node = new ArcNode; node->adjVertex = n; node->next = g.vertexs[m].firstArc; g.vertexs[m].firstArc = node; ArcNode *node1 = new ArcNode; node1->adjVertex = m; node1->next = g.vertexs[n].firstArc; g.vertexs[n].firstArc = node1; } } void Print(Graph g) { for(int i = 0;i<g.vertexNum;i++) { cout << g.vertexs[i].data; ArcNode *p = g.vertexs[i].firstArc; while(p) { cout<<"-->"<<g.vertexs[p->adjVertex].data; p = p->next; } cout <<endl; } } int FirstAdjVex(Graph g,int v)//返回v的第一個(gè)鄰接頂點(diǎn)序號(hào) { ArcNode *p = g.vertexs[v].firstArc; if(p!= NULL) return p->adjVertex; else return -1; } int NextAdjVex(Graph g,int v,int w) //返回頂點(diǎn)v相對(duì)于w的下一個(gè)鄰接點(diǎn)的序號(hào) { ArcNode *p = g.vertexs[v].firstArc; while(p) { if(p->adjVertex == w) break; p = p->next; } if(p->adjVertex !=w || !p->next) return -1; return p->next->adjVertex; } //求割點(diǎn) int countN; int visted[MAXN]; int low[MAXN]; void DFSCutPoint(Graph g,int v0) { int min = 0,w; visted[v0] = min = ++countN;;//v0是第count個(gè)訪問(wèn)的頂點(diǎn),min的初值為visited[v0],即v0的訪問(wèn)次序 for(ArcNode *p = g.vertexs[v0].firstArc;p;p=p->next) { w = p->adjVertex; if(!visted[w]) { DFSCutPoint(g,w);//從第w個(gè)頂點(diǎn)出發(fā)深搜,查找并輸出關(guān)節(jié)點(diǎn)(割點(diǎn)),返回前求得low[w] if(low[w] < min)//如果v0的孩子節(jié)點(diǎn)w的low[]小,說(shuō)明孩子節(jié)點(diǎn)還與其他節(jié)點(diǎn)(祖先)相鄰 min = low[w]; if(low[w]>=visted[v0] ) //v0的孩子節(jié)點(diǎn)w只與v0相連,則v0是關(guān)節(jié)點(diǎn)(割點(diǎn)) cout<<g.vertexs[w].data<<" "; } else if(visted[w] < min)//w已訪問(wèn),則w是v0生成樹(shù)上祖先,它的訪問(wèn)順序必小于min min =visted[w]; } low[v0] = min;//low[v0]取三者最小值 } void FindCutPoint(Graph g) { visted[0] = true; for(int i = 1;i<g.vertexNum;i++) visted[i] = false; ArcNode *p=g.vertexs[0].firstArc; int v = p->adjVertex; DFSCutPoint(g,v); if(countN < g.vertexNum) { cout << g.vertexs[0].data<<" "; while(p->next) { p = p->next; v = p->adjVertex; if(!visted[v]) DFSCutPoint(g,v); } } } int main() { Graph g; Create(g); cout<<"割點(diǎn)如下: "<<endl; FindCutPoint(g); return 0;
轉(zhuǎn)載于:https://www.cnblogs.com/tham/p/6827246.html
總結(jié)
以上是生活随笔為你收集整理的求一个连通图的割点(去掉一个点后图不再连通)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 新书品读《三级网络技术预测试卷与考点解析
- 下一篇: IDEA实用快捷键