#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 120
typedef long long ll;
int n,used[MAXN],mincost[MAXN]; //n个点,访问标记,最小距离
struct edge{int to,cost;
edge (){}
edge (int to,int cost):to(to),cost(cost){}
};
vector <edge> G[MAXN]; //存放从i出发的边
typedef pair<int,int> P; //重命名
priority_queue<P,vector<P>,greater<P>> que; //first存放距离,second存放节点
void prim(){ //每次找与当前点集相连的边中最短的边,看能否松驰
int res = 0; //答案初始为0
memset(used,0,sizeof(used)); //标记位清空
fill(mincost,mincost+n,INF); //边权最大化
que.push(P(0,0)); //从0点起到0点连边,边权为0
while (!que.empty()){ //队列非空
P p = que.top();que.pop(); //读出队首元素并弹出
int v = p.second,d = p.first; //vertex,distance
if (used[v]) continue; //已访问则跳过
used[v] = 1; //打上访问标记
res += d; //答案就加上d
for (int i = 0; i < G[v].size(); i += 1){ //遍历这个点射出的边
edge e = G [v][i]; //第i条边记为e
if ((mincost[e.to]> e.cost) && !used[i]){ //该点未被使用
mincost[e.to] = e.cost; //更新到该点(从0点起)最小花费
que.push(P(mincost[e.to],e.to)); //押入队列
}
}
}
printf("%d\n",res); //输出答案
}
int main(){
while (scanf("%d",&n) != EOF){ //N个点
memset(G,0,sizeof(G)); //每次都要初始化
for (int i = 0; i < n; i += 1){ //边起点
for (int j = 0; j < n; j += 1){ //边终点
int a;cin >> a; //i到j的距离
G[i].push_back(edge(j,a)); //打入邻接表
}
}
prim(); //跑最小生成树
}
return 0;
}
/*
Prim算法
此为堆优化后的模板
in
3
0 1 10
1 0 20
10 20 0
out
11
*/
4图-1最小生成树prim(priority_queue优化)
最新推荐文章于 2023-01-27 21:24:51 发布