#include<iostream>
#include<iomanip>
using namespace std;
typedef char VerType;
#define MAXNUM 20
// 邻接矩阵的定义
typedef struct {
VerType Vers[MAXNUM]; //1 顶点 数组 一维数组
int Arcs[MAXNUM][MAXNUM]; //2 边 二维数组 邻接矩阵
int VerNum; //3 点数
int ArcNUm; //4 边数
}AMGraph;
// 在图G的顶点数组中找顶点v的位置 下标
int LocateVer(AMGraph G,VerType v){
for(int i=0;i<G.VerNum;i++){
if(G.Vers[i]==v) return i;
}
}
//创建邻接矩阵
void createGraph(AMGraph &G){
cin>>G.VerNum>>G.ArcNUm; //首先,输入点数、边数
int i,j,k;
VerType x,y;
for(i=0;i<G.VerNum;i++) cin>>G.Vers[i]; //第二,输入点的信息
for(i=0;i<G.VerNum;i++) //在给邻接矩阵赋值之前,全部元素先清零
for(j=0;j<G.VerNum;j++)
G.Arcs[i][j]=0;
for(k=1;k<=G.ArcNUm;k++){ //第三,输入边的信息
cin>>x>>y; //输入边的两个顶点
i = LocateVer(G,x); //在顶点数组中找顶点x的位置 下标
j = LocateVer(G,y);
G.Arcs[i][j]=G.Arcs[j][i]=1; //修改邻接矩阵中对应位置的值 无向图 两个位置
}
}
//显示图的邻接矩阵
void printGraph(AMGraph G){
int i;
cout<<"顶点数="<<G.VerNum<<" 边数="<<G.ArcNUm<<"邻接矩阵如下:\n";
for(i=0;i<G.VerNum;i++){
for(int j=0;j<G.VerNum;j++) cout<<setw(3)<<G.Arcs[i][j];
cout<<"\n";
}
cout<<"顶点数组如下:\n";
for(i=0;i<G.VerNum;i++) cout<<setw(3)<<i;
cout<<"\n";
for(i=0;i<G.VerNum;i++) cout<<setw(3)<<G.Vers[i];
cout<<"\n";
}
int visited[MAXNUM]={0}; //全局 辅助数组 用来标记顶点是否访问过 0 未访问 1 已访问
//DFS 依次只能访问到当前连通分量中的顶点 其余不连通的顶点是无法访问的
//所以,对于非连通图,需要多次启动DFS
void DFS(AMGraph G, int v){
cout<<G.Vers[v]<<" "; visited[v]=1; //输出顶点v 并做标记
for(int w=0;w<G.VerNum;w++){ //扫描邻接矩阵中第v行,找顶点v的邻接点w
if(G.Arcs[v][w]==1 && visited[w]==0) //如果顶点w没有被访问
DFS(G,w); //从w开始,继续深度优先搜索
}
}
//遍历所有的顶点
void DFSALL(AMGraph G){
for(int i=0;i<G.VerNum;i++){
if( visited[i]==0){ //如果顶点i 没有被访问,从i开始DFS
DFS(G,i); //每次调用DFS,计数器加1
}
}
}
//在遍历的基础上,统计连通分量的个数 并分别显示连通分量中的结点
int DFSALL_2(AMGraph G){
int count=0;
for(int i=0;i<G.VerNum;i++){
if( visited[i]==0){ //如果顶点i 没有被访问,从i开始DFS
count++; cout<<"\n\n第"<<count<<"个连通分量结点内容如下:\n";
DFS(G,i); //每次调用DFS,计数器加1
}
}
return count;
}
int main(){
AMGraph G; //定义邻接矩阵存储的图G
createGraph(G); //创建G
printGraph(G); //显示G
cout<<"\n\nDFS的结果:" ;
//DFS(G,0); //从顶点0开始深度优先搜索
//DFSALL(G); //遍历图中所有顶点
//利用DFS求图中连通分量的个数
int r= DFSALL_2(G);
cout<<"\n\n图中有"<<r<<"个连通分量\n";
}
/*
//例1 一个连通图
8 8
abcdefgh
a b
a c
b d
b e
c f
c g
d h
e h
//例2 一个非连通图
6 4
abcdef
a b
b c
c d
e f
*/