这是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算法基本一样,对所有的边遍历,如果两个顶点在同一集合说明有环,否则将他们合并。如果有两个以上连通分支说明非连通图。

下面是代码:

 

 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 }

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-07-29
  • 2021-10-08
  • 2022-12-23
  • 2021-05-27
  • 2021-12-05
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-28
  • 2022-12-23
  • 2021-11-16
  • 2022-12-23
相关资源
相似解决方案