老师的题目::
实验内容
已知某地区的公路网以图表示,图中的顶点表示站点,任意两站点间的路段以带权的边构成的邻接矩阵表示,矩阵中非零元表示两个站点间存在直接的路段,否则没有路段。
打开E:\Test文件夹中的exp06.cpp文件,补充编写所需代码。程序首先进行图的连通性判定,若图连通则输出连通信息,否则继续计算和输出图的连通分量数。
输入数据在文件exp06.in中,首行的整数是站点的总数n(1<n<=30);第2行开始的n行中,每行n个整数,是这n个站点构成的公路网的邻接矩阵。例如,
6
01 3 4 9 0
10 9 9 0 0
39 0 0 6 8
49 0 0 5 7
90 6 5 0 4
00 8 7 4 0
主函数中,在调用读入数据函数readData()时,会自动将矩阵中的零元(除对角线保持0以外)替换成无穷大(9999)。
Search(intv)函数实现从顶点v出发的一次搜索过程,并累计访问顶点数。
若图是连通的,则输出文件exp06.out中包含如下文字:
All vertexsare connected.
否则,计算和输出连通分量数,输出文件的内容则如下例:
The number of connected components is 2.
解题思路
利用一次深度优先或者广度优先搜索过程中对访问顶点数的计数,并判断其与图的顶点总数是否相等来判定图的连通性。
如果图不连通,则继续从下一个未被访问的顶点出发再进行一次搜索,如此反复,直到已遍历图的所有顶点,累计的搜索次数即是图的连通分量数。
我在代码中都做了注解
#include <iostream>
#include <stdio.h>
using namespace std;
const int Size=30;
const double INF=9999; // infinity (无穷大)
int vexnum; // total number of vertex (顶点总数)
int adjmat[Size][Size]; // adjacent matrix (邻接矩阵)
int mark[Size]; // vector of visiting mark of vertex (顶点访问标记向量)
int visitnum; // number of visited vertex for one search (一次搜索中被访问顶点数)
int adjnum; // number of connected components (连通分量数)
void readData()
{ int i,j;
cin>>vexnum; // input vexnum
for(i=0; i<vexnum; i++)
for(j=0; j<vexnum; j++)
{ cin>>adjmat[i][j];
if(i!=j && adjmat[i][j]==0) adjmat[i][j]=INF;
}
}
/*int first_adj(int v){
int w;
for(w=0;w<vexnum;w++)
if(adjmat[v][w]!=INF||v!=w) return w;
return -1;
}
int next_adj(int v,int w){
for(w+=1;w<vexnum;w++)
if(adjmat[v][w]!=INF||v!=w) return w;
return -1;
}*/
void Search(int v) // one time search, v represents the starting vertex
{//************************************************
//********************************************
/*int w=-1; //书上的解法,太麻烦了
mark[v]=1;
visitnum++;
w=first_adj(v);
while(w!=-1){
if(!mark[w])
Search(w);
w=next_adj(v,w);
}*/
//==============================================
//**************************************************
/*递归的深度优先搜索
int i;
if(mark[v]==1) return; //访问过了,要有,可用于判断连通分量
mark[v]=1; //否则访问他
visitnum++;
for(i=0;i<vexnum;i++){
if(adjmat[v][i]!=INF&&v!=i&&mark[i]!=1) //找到未访问过的邻接点
Search(i);
}
return;*/
//====================================================
//***************************************************
/*
//非递归的深度优先搜索
int *stack=new int[vexnum],top=-1,w;
if(mark[v]==1) return;
stack[++top]=v;
mark[v]=1;
visitnum++;
while(top!=-1){
v=stack[top]; //不能top--,因为后面还要用到此处节点
for(w=0;w<vexnum;w++){//找一个未访问的邻接点,可以使用上面的first_adj(v)
if(adjmat[v][w]!=INF && v!=w && mark[w]!=1)
break;
}
if(w==vexnum) top--; //此节点 没有 还没找过的邻接点了,退栈
else{ //有未访问邻接点,人栈,接下来从这个节点继续深度访问
stack[++top]=w;
mark[w]=1;
visitnum++;
}
}
*/
//=====================================================
//*******************************************
/*
//广度优先搜索 先访问再入队
int *queue=new int[vexnum+1],front=0,rear=0;
int w;
if(mark[v]==1) return;
mark[v]=1;
visitnum++;
queue[rear++]=v;
while(front!=rear){
v=queue[front++];
for(w=0;w<vexnum;w++){ //找到所有未访问邻接点入队
if(adjmat[v][w]!=INF&&v!=w&&mark[w]!=1){
queue[rear++]=w;
mark[w]=1;
visitnum++;
}
}
//找完了
}
//========================================
*/
//================================================
}
int main()
{ int i;
/* freopen("exp06.in", "r", stdin);
freopen("exp06.out", "w", stdout);*/
readData(); // input data
for(i=0; i<vexnum; i++) mark[i]=0; // initialze the visiting mark
visitnum=0;
Search(0); // one time search from vertex 0
if(visitnum==vexnum) cout<<"All vertexs are connected.\n";
else
{ adjnum=1;
//************************************************
for(i=0;i<vexnum;i++){
if(!mark[i]){
Search(i);
adjnum++;
}
}
//================================================
cout<<"The number of connected components is "<<adjnum<<".\n";
}
return 0;
}