咳咳,一道最小生成树的水题
两点的边权为两个点+距离*2 因为最小生成树无环 一条边走两次
然后用克鲁斯卡尔就行
直接贴代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10005
#define M 100005
using namespace std;
int n,m,cnt,head[N],fa[N],arr[N],t[N],mn=0x3f3f3f3f;
long long mst,ans;
struct Node{
int to,nxt,w,frm;
}edge[M*2];
bool cmp(Node x,Node y)
{
return x.w<y.w;
}
void add(int x,int y,int z)
{
cnt++;
edge[cnt].to=y;
edge[cnt].frm=x;
edge[cnt].nxt=head[x];
edge[cnt].w=z*2+t[x]+t[y];
head[x]=cnt;
}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void kruscal()
{
for(int i=1;i<=n;i++) fa[i]=i;
sort(edge+1,edge+cnt+1,cmp);
for(int i=1;i<=cnt;i++)
{
int u=find(edge[i].frm), v=find(edge[i].to);
if(u!=v)
{
fa[v]=u;
mst+=edge[i].w;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
mn=min(mn,t[i]);
}
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
kruscal();
mst+=mn;
printf("%lld\n",mst);
return 0;
}