# [数据结构] DS图—最小生成树

n个顶点

m条边信息,格式为：顶点1 顶点2 权值
Prim算法的起点v

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>

using namespace std;

#define MAX_WEIGHT 99999

struct
{
int weight;
} Close_Edge[100]; //该点周围权值最小的边

class MGraph
{
public:
int Graph_Prim[100][100], Graph_Kruskal[100][100]; //图的权值矩阵
int n, nedge; //n是节点个数，len是边个数
int visited[100]; //Prim中标记已连接的点
string *node; //存放节点名
string start; //Prim开始节点
int startpos; //Prim开始位置
MGraph() {}
void SetMGraph();
void Prim();
void Kruskal();
};

void MGraph::SetMGraph() //数值输入及初始化
{
int i, j;
cin>>n;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
Graph_Prim[i][j] = 10000;
Graph_Kruskal[i][j] = 10000;
}
}

node = new string[n];
for(i=0; i<n; i++)
cin>>node[i];

cin>>nedge;
for(i=1; i<=nedge; i++)
{
string ch1, ch2;
int weight_;
cin>>ch1>>ch2>>weight_;
int loc1, loc2;
for(j=0; j<n; j++)
{
if(node[j]==ch1)
loc1 = j;
if(node[j]==ch2)
loc2 = j;
}
//构建权值矩阵
Graph_Kruskal[loc1][loc2] = Graph_Prim[loc1][loc2] = weight_;
Graph_Kruskal[loc1][loc2] = Graph_Prim[loc2][loc1] = weight_;
/*Graph_Prim[loc1][loc2] = weight_;
Graph_Prim[loc2][loc1] = weight_;
Graph_Kruskal[loc1][loc2] = weight_;
Graph_Kruskal[loc2][loc1] = weight_;*/
}
cin>>start;
for(i=0; i<n; i++) //确定Prim开始位置
if(node[i]==start)
startpos = i;
}

void MGraph::Prim()
{
int i, j;
for(i=1; i<=n; i++)
visited[i] = 0;
visited[startpos] = 1;
int min_;

//找出每个点周围权值最小的边及其邻接的点
for(i=0; i<n; i++)
{
min_ = MAX_WEIGHT;
for(j=0; j<n; j++)
{
if(Graph_Prim[i][j]<min_)
{
min_ = Graph_Prim[i][j];
Close_Edge[i].weight = min_;
}
}
}

string s3;
string *e1,*e2;
int *w3;
e1=new string[100];
e2=new string[100];
w3=new int[100];

int index, k=0;
for(i=0; i<n; i++) //这里可能要修改为从起始点start开始
{
min_ = MAX_WEIGHT;
for(j=0; j<n; j++)
{
if(!visited[j])
continue;
else
{
if(min_>Close_Edge[j].weight)
{
min_ = Close_Edge[j].weight;
index = j;
}
}
}
e1[k] = node[index];
e2[k] = s3; w3[k++] = min_;

for(int g=0; g<n; g++) //标记已连接的点
{
if(node[g]==s3)
{
visited[g] = 1;
break;
}
}
for(int g=0; g<n; g++) //更新Close_Edge
{
min_ = MAX_WEIGHT;
for(int m=0; m<n; m++)
{
if(min_>Graph_Prim[g][m] && visited[m]==0)
{
min_ = Graph_Prim[g][m];
Close_Edge[g].weight=min_;
}
}
}
}
int Weight=0;
for(i=0; i<k-1; i++)
{
Weight+=w3[i];
}
cout<<Weight<<endl;
cout<<"prim:"<<endl;
for(i=0; i<k-1; i++)
cout<<e1[i]<<" "<<e2[i]<<" "<<w3[i]<<endl;
}

void MGraph::Kruskal()
{
cout<<"kruskal:"<<endl;
int *uni = new int[n];

//标记哪些点相连，uni值相同表示这些点在一个连通分量内
for(int i=0; i<n; i++)
uni[i] = i;

for(int i=0; i<n-1; i++)
{
int min=MAX_WEIGHT;
int x, y;
for(int j=0; j<n; j++) //找出权值最小的边
{
for(int k=0; k<n; k++)
{
if(j==k)
continue;
if(uni[j]==uni[k])
continue;
else
{
if(min>Graph_Kruskal[j][k])
{
min = Graph_Kruskal[j][k];
x=j; y=k;
}
}
}
}
Graph_Kruskal[x][y] = MAX_WEIGHT;
Graph_Kruskal[y][x] = MAX_WEIGHT;

if(x>y) //确保最后升序输出，x要小于y
swap(x, y);

for(int i=0; i<n; i++)
{
if(uni[i]==uni[y] && i!=y) //如果点y已经在包含多个点的连通分量内
uni[i] = uni[x];
}
uni[y] = uni[x];
cout<<node[x]<<" "<<node[y]<<" "<<min<<endl;
}
}

int main()
{
MGraph m,M;
m.SetMGraph();
m.Prim();
m.Kruskal();
return 0;
}

• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

02-27

04-08 511
11-11 75
12-21 531
11-07 2612
01-05 452
06-17 51
11-27 239
11-18 44
04-14 720
09-23 95
05-31 870