判断图连通性的三种方法

       在看哥尼斯堡七桥问题的时候,谈到欧拉回路的问题,不免又想到了图的连通性。想到以后说不定会遇到相关问题,就做下连通性判断算法总结实现。如果一个图是连通的,那么从一个节点开始访问,采用深度优先或者广度优先对它进行遍历,那么必定能够访问完所有的节点。还有一种方法,就是使用图的邻接矩阵的传递闭包。下面是三种方法的实现代码。

#include<iostream>
#include<queue>
#include <stdio.h>

using namespace std;

#define MAX_VNUM 10

typedef struct
{
 int weight;
}Adj,AdjMatrix[MAX_VNUM][MAX_VNUM];

typedef struct
{
 AdjMatrix adjM;
 int vNum;
}adjGraph;

//创建一个图,节点从0开始,注意传入引用
void CreateGraph(adjGraph &G)
{
 cout<<"输入节点个数:"<<endl;
 cin>>G.vNum;
 cout<<"输入图的邻接矩阵:"<<endl;
 for (int i=0;i<G.vNum;i++)
 {
  for (int j=0;j<G.vNum;j++)
  {
   cin>>G.adjM[i][j].weight;
  }
 }
}

//输出一个图
void print(adjGraph G)
{
 for(int i=0;i<G.vNum;i++)
 {
  for(int j=0;j<G.vNum;j++)
  {
   cout<<G.adjM[i][j].weight<<" ";
  }
  cout<<endl;//将换行流写入输出流,清空输出缓冲区
 }
}


//warshall算法判断图的连通性
bool connectivityWarshall(adjGraph G)
{
 adjGraph temp;//临时判断矩阵
 temp.vNum = G.vNum;

 //初始化临时判断矩阵
 for (int i =0;i<temp.vNum;i++)
 {
  for(int j=0;j<temp.vNum;j++)
  {
   if (G.adjM[i][j].weight)
    temp.adjM[i][j].weight = 1;
   else
    temp.adjM[i][j].weight = 0;

  }
  temp.adjM[i][i].weight = 1;
 }

 //矩阵乘法算法Warshall,R(a)
 for (int a =0;a<temp.vNum;a++)
 {
  for (int b=0;b<temp.vNum;b++)
  {
   if(temp.adjM[a][b].weight)
   {
    for (int c = 0;c<temp.vNum;c++)
    {
     if (temp.adjM[c][a].weight)
      temp.adjM[c][b].weight = 1;
    }
   }
  }
 }

 //进行判断
 for (int i=0;i<temp.vNum;i++)
 {
  for (int j=0;j<temp.vNum;j++)
  {
   if (!temp.adjM[i][j].weight)
    return false;
  }
 }

 return true;
}


//广度优先搜索判断连通性
bool connectivityBFS(adjGraph G)
{
 queue<int> q; //明白队列用途?
 bool visit[MAX_VNUM]; //访问数组
 int count = 0;

 memset(visit,0,sizeof(visit));

 q.push(0); //0节点入队列

 while(!q.empty())
 {
  int v = q.front();
  visit[v] = true;
  q.pop();
  count++;

  //与联通且没有被访问过节点入队列
  for (int i =0;i<G.vNum;i++)
  {
   if (G.adjM[v][i].weight)
   {
    if(!visit[i])
    {
     q.push(i);
    }
   }
  }
 }

 if (count == G.vNum) return true;
 else return false;

}

//深度优先搜索判断图的连通性,传递数组会改变值,visit需初始化
void dfs_visit(adjGraph G,int firstNode,bool visit[])
{
 visit[firstNode] = 1;

 for(int i=0; i<G.vNum;i++)
 {
  if(G.adjM[firstNode][i].weight & !visit[i])
   dfs_visit(G,i,visit);
 }
}

bool connectivityDFS(adjGraph G)
{
 bool visit[MAX_VNUM]; //访问数组
 memset(visit,0,sizeof(visit));
 dfs_visit(G,0,visit); //从0节点开始访问

 for(int i=0;i<G.vNum;i++)
 {
  if (visit[i] == false) return false;
 }

 return true;
}

int main()
{
 adjGraph G;
 CreateGraph(G);
 //print(G);

 if (connectivityWarshall(G)) cout<<"连通"<<endl;
 else cout<<"不连通"<<endl;
 system("pause");
 return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值