数据结构 图连通与最小生成树
Posted 上山打老虎D
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 图连通与最小生成树相关的知识,希望对你有一定的参考价值。
连通与最小生成树
1. DS图—最小生成树
题目描述
根据输入创建无向网。分别用Prim算法和Kruskal算法构建最小生成树。(假设:输入数据的最小生成树唯一。)
输入
顶点数n
n个顶点
边数m
m条边信息,格式为:顶点1顶点2权值
Prim算法的起点v
输出
输出最小生成树的权值之和
对两种算法,按树的生长顺序,输出边信息(Kruskal中边顶点按数组序号升序输出)
输入样例
6
v1 v2 v3 v4 v5 v6
10
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6
v1
输出样例
15
prim:
v1 v3 1
v3 v6 4
v6 v4 2
v3 v2 5
v2 v5 3
kruskal:
v1 v3 1
v4 v6 2
v2 v5 3
v3 v6 4
v2 v3 5
参考代码
#include<iostream>
#include<cstring>
using namespace std;
const int maxx= 100;
int n;
int array[maxx][maxx];
class Kru{//存储kruskal算法中的节点
public:
int bef;
int aft;
int data;
int flag;
Kru(){
bef= -1;
aft= -1;
data= 0;
flag= 0;
}
};
void prim(string str[], int n, int po){//prim算法
int index= po;//开始遍历的顶点
int sum= 0;
int visit[n+ 5];//记录每个顶点是否被访问
int dist[n+ 5];//最小树的权重集合
int pos[n+ 5]; //最小树与dist[]对应的顶点
memset(visit, false, sizeof(visit));
visit[index]= true;
int bef= index;
for(int i= 0; i< n ; i++){//初始dist集合为开始顶点的相邻点
dist[i]= array[index][i];
pos[i]= index* 100+ i;//表示index 与i连通,记录x坐标和y坐标
}
//string ss= "";
string beff[n+ 5];//每条边的头
string aft[n+ 5];//每条边的尾
int quan[n+ 5];//每条边的权重
int r= 0;
for(int i= 1; i< n; i++){
int minn= 10000;
for(int j= 0; j< n; j++){
if(!visit[j]&&dist[j]< minn){//找出dist[]中的最小的那条边
minn= dist[j];
index= j;
}
}
visit[index]= true;
beff[r]= str[pos[index]/100];
aft[r]= str[index];
quan[r++]= dist[index];
sum+= dist[index];
for(int j= 0; j< n; j++){
if(!visit[j]&&dist[j]> array[index][j]){//查找下一个顶点相连的边是否还有更小的,
//有则更新
dist[j]= array[index][j];
pos[j]= index* 100+ j;
}
}
}
cout<<sum<<endl<<"prim:"<<endl;
for(int i= 0; i< r; i++){
cout<<beff[i]<<' '<<aft[i]<<" "<<quan[i]<<endl;
}
}
int findmin(Kru kr[], int in){//找出kr[]数组中权重最小的边
int minn= 10000;
int index= 0;
int flag= 0;
for(int i= 0; i< in; i++){
if(!kr[i].flag&&kr[i].data< minn){//如果该边没被访问且最小
minn= kr[i].data;
index= i;
flag= 1;
}
}
return index;
}
int find(string str[], int n, string st){//返回st字符串的下标
for(int i= 0; i< n; i++)
if(str[i]== st)
return i;
}
void change(int visit[], int n, int a, int b){//将两个顶点及与他们相通的顶点改成同样的值表示
//他们相通
for(int i= 0; i< n; i++)
if(visit[i]== a)
visit[i]= b;
}
void kruskal(string str[], int in, int n, Kru kr[]){//kruskal算法
int visit[n+ 5];
for(int i= 0; i< n; i++)
visit[i]= i;//初始visit[]数组
//int k= 0;
cout<<"kruskal:"<<endl;
int k= 0;
while(true){
int minn= findmin(kr, in);//找出权重最小的边
kr[minn].flag= 1;
int t1= kr[minn].bef;
int t2= kr[minn].aft;
if(visit[t1]!= visit[t2]){//如果两个顶点的visit值不一样说明还没相通
if(t1> t2){
int t= t1;
t1= t2;
t2= t;
}
cout<<str[t1]<<" "<<str[t2]<<" "<<kr[minn].data<<endl;
change(visit, n, visit[t1], visit[t2]);//将两个顶点连通
}
k++;
if(k>= in)
break;
}
}
int main(){
cin>>n;
string str[100];
for(int i= 0; i< n; i++)
cin>>str[i];
for(int i= 0; i< n; i++)
for(int j= 0; j< n; j++)
array[i][j]= 10000;
int in;
cin>>in;
Kru kr[in+ 5];
for(int j= 0; j< in; j++){
string s1;
string s2;
int shu;
cin>>s1>>s2>>shu;
//prim
int t1= find(str, n, s1);
int t2= find(str, n, s2);
array[t1][t2]= shu;
array[t2][t1]= shu;
//krushal
kr[j].bef= t1;
kr[j].aft= t2;
kr[j].data= shu;
kr[j].flag= 0;
}
string s;
cin>>s;
int d= find(str, n, s);
prim(str, n, d) ;
kruskal(str, in, n, kr);
return 0;
}
2. DS图—图的连通分量
题目描述
输入无向图顶点信息和边信息,创建图的邻接矩阵存储结构,计算图的连通分量个数。
输入
测试次数t
每组测试数据格式如下:
第一行:顶点数 顶点信息
第二行:边数
第三行开始,每行一条边信息
输出
每组测试数据输出,顶点信息和邻接矩阵信息
输出图的连通分量个数,具体输出格式见样例。
每组输出直接用空行分隔。
输入样例
3
4 A B C D
2
A B
A C
6 V1 V2 V3 V4 V5 V6
5
V1 V2
V1 V3
V2 V4
V5 V6
V3 V5
8 1 2 3 4 5 6 7 8
5
1 2
1 3
5 6
5 7
4 8
输出样例
A B C D
0 1 1 0
1 0 0 0
1 0 0 0
0 0 0 0
2
V1 V2 V3 V4 V5 V6
0 1 1 0 0 0
1 0 0 1 0 0
1 0 0 0 1 0
0 1 0 0 0 0
0 0 1 0 0 1
0 0 0 0 1 0
1
1 2 3 4 5 6 7 8
0 1 1 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 1 0
0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0
3
参考代码
#include<iostream>
#include<cstring>
using namespace std;
int find(string str[], string st, int n){
for(int i= 0; i< n; i++)
if(str[i]== st)
return i;
}
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
string str[200];
for(int i= 0; i< n; i++)
cin>>str[i];
int array[n+ 5][n+5];
for(int i= 0; i< n+ 5; i++)
for(int j= 0 ; j< n+ 5; j++)
array[i][j]= 0;
int in;
cin>>in;
for(int i= 0 ; i< in; i++){
string s1;
string s2;
cin>>s1>>s2;
int a= find(str, s1, n);
int b= find(str, s2, n);
array[a][b]= 1;
array[b][a]= 1;
}
for(int i= 0; i< n; i++){
cout<<str[i];
if(i!= n- 1)
cout<<" ";
}
cout<<endl;
for(int i= 0; i< n; i++){
for(int j= 0; j< n; j++){
cout<<array[i][j];
if(j!= n- 1)
cout<<" ";
}
cout<<endl;
}
int arr[n+ 5];
for(int i= 0; i< n+ 5; i++)
arr[i]= i;
for(int i= 0; i< n; i++){
for(int j= 0; j< n ;j++){
if(array[i][j]){
for(int k= 0; k< n;k++)
if(arr[k]== arr[i])
arr[k]= arr[j];
}
}
}
// for(int i= 0; i< n; i++){
// cout<<arr[i]<<"--";
// }
// cout<<endl;
int shu[n+ 5];
for(int i= 0; i< n ;i++)
shu[i]= 0;
for(int i= 0; i< n+ 5; i++)
shu[arr[i]]++;
int sum= 0;
for(int i= 0; i< n; i++){
if(shu[i])
sum++;
}
cout<<sum<<endl<<endl;
}
return 0;
}
3. 图的应用之——图的连通
题目描述
给定一个图的邻接矩阵,请判断该图是否是连通图。连通图:任意两个顶点之间都有路径。
–程序要求–
若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求
输入
第1行输入一个整数k,表示有k个测试数据
第2行输入一个整数n,表示有n个结点
从第3行起到第n+2行输入一个邻接矩阵,其中Matrix[i,j]=1表示第i,j个结点之间有边,否则不存在边。
接下来是第2到第k个测试数据的结点数和邻接矩阵
输出
输出Yes or No表示图是否是强连通图
输入样例
2
4
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
7
0 1 0 0 0 0 0
0 0 1 1 0 0 0
1 0 0 0 0 0 0
1 0 1 0 0 0 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 0 0 1 0 1 0
输出样例
Yes
No
参考代码
#include<iostream>
using namespace std;
const int MaxLen = 20;
class Map
{
private:
bool Visit[MaxLen];
int Matrix[MaxLen][MaxLen];
int Vexnum;
void DFS(int v)
{
int w, i, k;
Visit[v] = true;
count1++;
//cout<<v<<" ";
//寻找邻接点
int *AdjVex = new int[Vexnum];
for (i = 0; i < Vexnum; i++)
AdjVex[i] = -1;
k = 0;
for (i = 0; i < MaxLen; i++)
if (Matrix[v][i] == 1)
AdjVex[k++] = i;
i = 0;
for (w = AdjVex[i++]; w >= 0; w = AdjVex[i++])
{
if (Visit[w] == false)
DFS(w);
}
delete[]AdjVex;
}
public:
int count1;
void SetMatrix(int vnum, int mx[MaxLen][MaxLen])
{
int i, j;
Vexnum = vnum;
for (i = 0; i < MaxLen; i++)
for (j = 0; j < MaxLen; j++)
Matrix[i][j] = 0;
for (i = 0; i < Vexnum; i++)
for (j =以上是关于数据结构 图连通与最小生成树的主要内容,如果未能解决你的问题,请参考以下文章