题目描述
代码实现
prim实现版本:
//最小生成树问题
//使用prim算法
#include "bits/stdc++.h"
using namespace std;
//最大的顶点数
const int MAXV = 110;
//不可达的距离
const int INF = 0x3fffffff;
//由于n<100,所以采用邻接表的方式进行存储图
int G[MAXV][MAXV];
//输入的顶点数
int n;
//是否已经访问数组
bool vis[MAXV] = {false}; //初始化为false
//顶点到集合S的距离
int d[MAXV];
//最短距离
int ans;
int prim(){
//需要进行n-1次
for(int i=2;i<=n;i++){
//当前的最小值
int min = INF;
//当前最小值的下标
int idx = -1;
for(int i=1;i<=n;i++){
if(vis[i] == false && d[i] < min){
min = d[i];
idx = i;
}
}
//进行更新
vis[idx] = true;
ans += d[idx];
for(int i=1;i<=n;i++){
if(vis[i] == false && G[idx][i] < d[i]){
d[i] = G[idx][i];
}
}
}
return ans;
}
int main(){
while(~scanf("%d",&n)){
if(n == 0){
break;
}
//由于共享了数据结构,所以记得初始化!!!
fill(vis,vis+MAXV,false);
fill(G[0],G[0]+MAXV*MAXV,INF);
fill(d,d+MAXV,INF);
ans = 0;
int u,v,w;
//读入图
for(int i=0;i<(n*(n-1))/2;i++){
scanf("%d %d %d",&u,&v,&w);
G[u][v] = w;
G[v][u] = w;
}
//初始化S集合
vis[1] = true;
d[1] = 0;
for(int i=2;i<=n;i++){
d[i] = G[1][i];
}
ans = prim();
printf("%d\n",ans);
}
return 0;
}
kruskal实现版本:
//使用kruskal算法,它的时间复杂度要更加地优秀
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 5000;
struct edge{
int u;
int v;
int d;
edge(){}
// edge(int _u,int _v,int _d){
// u = _u;
// v = _v;
// d = _d;
// }
};
edge edges[maxn];
int father[maxn];
int n;
int m;
bool cmp(edge a,edge b){
return a.d < b.d;
}
int find(int x){
if(father[x]==x){
return x;
}else{
int root = find(father[x]);
father[x] = root;
return root;
}
}
int main(){
while(scanf("%d",&n)!=EOF && n!=0){
m = (n*(n-1))/2;
int dis = 0;
for(int i=0;i<m;i++){
int u,v,d;
scanf("%d %d %d",&u,&v,&d);
edges[i].u = u;
edges[i].v = v;
edges[i].d = d;
}
for(int i=0;i<=n;i++){
father[i]=i;
}
//进行一个排序
sort(edges,edges+m,cmp);
//然后进行遍历所有边求解最小生成树
for(int i=0;i<m;i++){
int u = edges[i].u;
int v = edges[i].v;
int fatherU = find(u);
int fatherV = find(v);
if(fatherU == fatherV){
continue;
}else{
//合并
father[fatherU] = fatherV;
dis += edges[i].d;
}
}
printf("%d\n",dis);
}
return 0;
}
码后反思
- 注意细节即可~~
- 由于树的边是一定的,所以
kruskal
算法可以增加一个判断边的数量从而提前终止!!!