無向圖是否是無環連通圖的判別


這是2020的最后一篇博客,對今天數據結構小測的一道題總結一下。

題目:給定頂點個數n和無向圖的鄰接矩陣bool m[graph_size][graph_size],寫出判斷是否為無環連通圖的函數bool Isconnectedacyclic()。

上午寫的時候只想到深搜/廣搜,下午聽老師講了一下,想到了其他方法,這里總結三種,如有錯誤請指正。

 

1.深搜/廣搜

本來我是打算寫深搜的,但由於給定的函數沒有參數,懶得再寫一個函數了。深搜應該是比較直接的方法,這里不多贅述

而廣搜比深搜麻煩的一點是新加入的點要考慮父節點,從而避免重復訪問。這里有兩種方法:一是對新加入的點記錄父節點,在對邊遍歷時遇到父節點則跳過;二是利用鄰接矩陣對邊訪問的特性,直接刪掉用過的邊和對稱的邊。下面給出第二種的代碼:

 1 bool Isconnectedacyclic()
 2 {
 3     vector<bool>vit(n,false);
 4     queue<int>que;
 5     bool flag=false;
 6     que.push(0);
 7     vit[0]=true;
 8     while(!que.empty())
 9     {
10         int p=que.front();
11         que.pop();
12         for(int i=0;i<graph_size;++i)
13         {
14             if(m[p][i])
15             {
16                 if(vit[i])flag=true;
17                 else
18                 {
19                     vit[i]=true;
20                     que.push(i);
21                 }
22                 m[p][i]=m[i][p]=false; //刪邊
23             }
24         }
25     }
26     if(flag)return false; //有回路
27     for(int i=0;i<n;++i)
28     {
29         if(!vit[i])return false; //非聯通圖
30     }
31     return true;
32 }

 

2.並查集:

其實跟kruskal算法基本一樣,對所有的邊遍歷,如果兩個頂點在同一集合說明有環,否則將他們合並。如果有兩個以上連通分支說明非連通圖。

下面是代碼:

 

 1 int f[n];
2
int find(int k) 3 { 4 if(f[k]==k)return k; 5 return f[k]=find(f[k]); 6 } 7 bool Isconnectedacyclic() 8 { 9 for(int i=0;i<n;++i)f[i]=i; 10 for(int i=0;i<graph_size;++i) 11 { 12 for(int j=i+1;j<graph_size;++j) 13 { 14 if(m[i][j]) 15 { 16 int fi=find(i),fj=find(j); 17 if(fi==fj)return false; 18 f[fi]=fj; 19 } 20 } 21 } 22 int cnt=0; 23 for(int i=0;i<n;++i) 24 { 25 if(f[i]==i)cnt++; 26 } 27 return cnt==1;
28 }

 

 

3.樹的性質:

寫的時候沒有想起(好不應該),一個無環連通圖正是一棵樹。根據樹的性質,邊數m=頂點數n -1,我們統計總共有多少條邊,如果m<n-1說明非連通;如果m>n-1說明必定有環;如果m==n-1,還要對圖進行一次遍歷,判斷是否為連通圖。

以下是代碼:

 

 1 bool Isconnectedacyclic()
 2 {
 3     int cnt=0;
 4     for(int i=0;i<graph_size;++i)
 5     {
 6         for(int j=i+1;j<graph_size;++j)
 7         {
 8             if(m[i][j])cnt++;
 9         }
10     }
11     if(cnt!=n-1)return false;
12     vector<bool>vit(n,false);
13     queue<int>que;
14     que.push(0);
15     vit[0]=true;
16     while(!que.empty())
17     {
18         int p=que.front();
19         que.pop();
20         for(int i=0;i<graph_size;++i)
21         {
22             if(m[p][i]&&!vit[i])
23             {
24                 vit[i]=true;
25                 que.push(i);
26             }
27         }
28     }
29     for(int i=0;i<n;++i)
30     {
31         if(!vit[i])return false;
32     }
33     return true;
34 }

 


免責聲明!

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



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