大神的答案(太绝了)https://blog.csdn.net/libin56842/article/details/19910291
看了好久才看懂,所以做了细化解析以防下次懵逼
书上写的最小生成树Prim很复杂,但是大佬用了巧妙的解法
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int inf = 1<<30;
int point[111111];
int pre[111111];
int n,m,sum;
struct node
{
int x,y,w;
} e[111111];
int cmp(node a,node b)
{
return a.w<b.w;
}
//Prim算法超级巧妙的用法
int find(int x)
{
if(pre[x]==x)
return x;
int t = find(pre[x]); //如果这条路被选过了,x端点的pre[x]会变成y
pre[x] = t;
return t;
}
int main()
{
int i,j,minn = inf;
scanf("%d%d",&n,&m); //n个点,m条边
for(i = 1; i<=n; i++) //从1开始
{
scanf("%d",&point[i]); //每个点的权重
minn = min(minn,point[i]); //找出权重最小的那个点成为休息点
pre[i] = i; //初始化pre
}
for(i = 1; i<=m; i++)
{
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); //x,y分别是牧场某一条路的两端点,w是走完路的时间
e[i].w = 2*e[i].w+point[e[i].x]+point[e[i].y]; //端点权重加上往返这条路(*2)
}
sort(e+1,e+m+1,cmp); //按权重排序
sum = 0;
for(i = 1;i<=m;i++)
{
int fx = find(e[i].x); //从权重最小的路开始,找两个端点
int fy = find(e[i].y);
if(fx!=fy)
{
sum+=e[i].w;
pre[fx] = fy; //如果fx != fy,那么fx = e[i].x,fy = e[i].y。(fx = fy)用来标记这条路已经被走过了
}
}
printf("%d\n",sum+minn);
return 0;
}