網易有道筆試:求連通圖的割點(關節點)


題目:求一個連通圖的割點,割點的定義是,如果除去此節點和與其相關的邊,圖不再連通,描述算法。

分析:

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的孩子節點將於其他節點被分割開來,從來形成新的連通分量。

[cpp]  view plain copy
  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. }  



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM