问题 A: 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 <string>
#include <algorithm>
#define INFINITY 999999
using namespace std;
struct Edge
{
int start,end,weight;
};
class Graph//没有使用动态数组,待优化
{
public:
int vexnum;
int edge;
int adjMatrix[20][20];//邻接矩阵
int begin;
string name[20];//结点信息
int value;
Edge edgeset[100];
int father[100]; //并查集
public:
void initial()
{
value=0;
cin >> vexnum;
for(int i=0;i<vexnum;i++){
cin >> name[i];
}
for(int i=0;i<20;i++)
for(int j=0;j<20;j++)
adjMatrix[i][j]=INFINITY;
cin >> edge;
for(int i=0;i<edge;i++){
string t1,t2;
int weight;
cin >> t1 >> t2 >> weight;
int a1,a2;
a1=find_index(t1);
a2=find_index(t2);
adjMatrix[a1][a2]=weight;
adjMatrix[a2][a1]=weight;//无向图
edgeset[i].start=a1;//初始化边数组
edgeset[i].end=a2;
edgeset[i].weight=weight;
}
string begin1;
cin >> begin1;
begin=find_index(begin1);
}
int find_index(string a)
{
for(int i=0;i<vexnum;i++)
if(!a.compare(name[i]))return i;
}
void Prim()/*n^2*/
{
int array[100]={
0};
int array1[100]={
0};
Edge *close_edge=new Edge[vexnum];
for(int i=0;i<vexnum;i++){
//对于所有的结点,初始化closeedge上原点到他们的距离 /*频度为n*/
if(i!=begin){
close_edge[i].start=begin;
close_edge[i].end=i;
close_edge[i].weight=adjMatrix[begin][i];
}
}
close_edge[begin].weight=-1;//表示原点已经加入U了
//然后访问剩下的顶点,依次加入U
for(int i=1;i<vexnum;i++){
/*n-1*/
//1.寻找close_edge中权重最小的边
int min=INFINITY,index;//index对应结点下标
for(int j=0;j<vexnum;j++){
/*频度为n-1*/
if(close_edge[j].weight!=-1&&close_edge[j].weight<min){
min=close_edge[j].weight;
index=j;
}
}
array[i]=index;
array1[i]=close_edge[index].weight;
value+=min;//权值
//2.将其加入集合U
close_edge[index].weight=-1;
//3.更新close_edge数组
for(int j=0;j<vexnum;j++){
//更新距离//优化名称 /*频度为n*/
if(adjMatrix[close_edge[index].end][j]<close_edge[j].weight){
//如果index到j的距离小于j的close_edge距离
close_edge[j].weight=adjMatrix[close_edge[index].end][j];
close_edge[j].start=close_edge[index].end;
close_edge[j].end=j;
}
}
}
cout << value << endl;
cout<<"prim:"<<endl;
for(int i=1;i<=vexnum-1;i++){
cout << name[close_edge[array[i]].start] << ' ' << name[close_edge[array[i]].end] << ' ' << array1[i] << endl;
}
}
int find(int pos)
{
if(father[pos]!=pos)return find(father[pos]);
else return pos;
}
void sort(Edge data[], int n)
{
for(int i=n-1;i>=1;i--){
for(int j=1;j<=i;j++){
if(data[j-1].weight>data[j].weight){
Edge temp=data[j-1];
data[j-1]=data[j];
data[j]=temp;
}
}
}
}
void Kruskal()
{
cout<<"kruskal:"<<endl;
for(int i=0;i<vexnum;i++)//结点之间在farther里顺序排列
father[i] = i;
sort(edgeset,edge);
/*从E中找到代价最小的边,且该边两点在不同的两个连通分量上*/
int k=0;//边数
for(int i=0;i<edge;i++){
if(k>=vexnum-1)break;
int a1,a2;
a1=find(edgeset[i].start);
a2=find(edgeset[i].end);
if(a1!=a2){
//这条边ok
father[a1]=a2;//合并并查集
k++;//有效边多了
cout << name[edgeset[i].start] << ' ' << name[edgeset[i].end] << ' ' << edgeset[i].weight << endl;
}
}
}
};
int main()
{
Graph graph;
graph.initial();
graph.Prim();
graph.Kruskal();
return 0;
}
目的
一个笔记
扫描二维码关注公众号,回复:
13112481 查看本文章
