题目描述
根据输入创建无向网。分别用Prim算法和Kruskal算法构建最小生成树。(假设:输入数据的最小生成树唯一。)输入
顶点数nn个顶点
边数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
两种方法需要用到不同的存储方法
推荐一个b站的up主懒猫老师的数据结构视频
文章链接https://www.bilibili.com/read/cv8013121
#include<iostream>
#include<cstring>
using namespace std;
#define maxx 100
string name[maxx];
class EdgeType{
public:
int from,to;
int weight;
EdgeType(){
from = to = 0;
weight=1000000;
}
EdgeType(const EdgeType &e){
from = e.from;
to = e.to;
weight = e.weight;
}
};
class Kruskal{
private:
EdgeType edge[maxx*maxx];
int n,side,cnt;
int parent[maxx];
public:
Kruskal(int num,int s){
n = num;
side = s;
cnt = 0;
}
void insert(int a,int b,int weight){
edge[cnt].from = a;
edge[cnt].to = b;
edge[cnt].weight = weight;
cnt++;
}
void sort(){
for(int i = 0; i < side - 1; i++){
for(int j = i + 1; j < side; j++){
if(edge[j].weight < edge[i].weight){
EdgeType temp(edge[j]);
edge[j] = edge[i];
edge[i] = temp;
}
}
}
}
int findParent(int v){
while(parent[v] > -1){
v = parent[v];
}
return v;
}
void outputMST(int i){
if(name[edge[i].from] > name[edge[i].to])
cout<<name[edge[i].to]<<" "<<name[edge[i].from]<<" "<<edge[i].weight<<"\n";
else
cout<<name[edge[i].from]<<" "<<name[edge[i].to]<<" "<<edge[i].weight<<"\n";
return ;
}
void func(){
sort();
cout<<"kruskal:\n";
for(int i; i < n; i++){
parent[i] = -1;
}
for(int num = 0, i =0; i < side; i++){
int vex1 = findParent(edge[i].from);
int vex2 = findParent(edge[i].to);
if(vex1 != vex2){
outputMST(i);
parent[vex2] = vex1;
num++;
if(num == n - 1){
return ;
}
}
}
}
};
int find(string a,int n) {
for (int i = 0; i < n; i++) {
if(a == name[i]){
return i;
}
}
}
struct shortEdge {
int lowcost;
int adjvex;
};
class Prim {
private:
int map[maxx][maxx];
int n;
public:
Prim(int input_n) {
n = input_n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
map[i][j] = 1000000;
}
}
}
void insert(int a,int b,int weight) {
map[a][b] = weight;
map[b][a] = weight;
}
int minEdge(shortEdge *s,int n) {
int min = 1000000,k = 0;
for(int i = 0; i < n; i++) {
if(s[i].lowcost != 0 && s[i].lowcost < min) {
min = s[i].lowcost;
k = i;
}
}
return k;
}
void func(int d) {
int start = d,sum = 0,k = 0;
shortEdge s[n];
//---------第一遍算权值和-----------
for(int i = 0; i < n; i++) {
s[i].lowcost = map[start][i];
s[i].adjvex = start;
}
s[start].lowcost = 0;
for(int i = 0; i < n - 1; i++) {
k = minEdge(s,n);
sum += s[k].lowcost;
s[k].lowcost = 0;
for(int j = 0; j < n; j++) {
if(map[k][j] < s[j].lowcost) {
s[j].lowcost = map[k][j];
s[j].adjvex = k;
}
}
}
cout<<sum<<endl;
//---------第二遍输出节点关系-----------
cout<<"prim:"<<"\n";
for(int i = 0; i < n; i++) {
s[i].lowcost = map[start][i];
s[i].adjvex = start;
}
s[start].lowcost = 0;
for(int i = 0; i < n - 1; i++) {
k = minEdge(s,n);
cout<<name[s[k].adjvex]<<" "<<name[k]<<" "<<s[k].lowcost<<endl;
s[k].lowcost = 0;
for(int j = 0; j < n; j++) {
if(map[k][j] < s[j].lowcost) {
s[j].lowcost = map[k][j];
s[j].adjvex = k;
}
}
}
}
};
int main() {
int num,side,weight;
string name1,name2;
cin >> num;
for(int i = 0; i < num; i++) {
cin>>name[i];
}
cin>>side;
Prim p(num);
Kruskal k(num,side);
while(side--) {
cin>>name1>>name2>>weight;
int a = find(name1,num), b = find(name2,num);
p.insert(a,b,weight);
k.insert(a,b,weight);
}
string s;
cin >>s;
int d = find(s,num);
p.func(d);
k.func();
return 0;
}