Description
Solution
很显然,如果要取一条边 (u,v) ,那么贡献值就会增加 (au+av) ,于是我们把所有边的边权减去边两边端点的 ax ,然后我们会得到一些互不影响的边权,于是跑一次最小生成树即可。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
#define ll long long
using namespace std;
ll a[N];
struct node{
int x,y;
ll z;
}b[N];
bool cmp(node x,node y)
{
return x.z<y.z;
}
int f[N];
int find(int x)
{
return !f[x]?x:f[x]=find(f[x]);
}
int main()
{
freopen("2.in","r",stdin);
freopen("2.out","w",stdout);
int n,m;
cin>>n>>m;
fo(i,1,n) scanf("%lld",&a[i]);
fo(i,1,m)
{
int x,y;
ll z;
scanf("%d %d %lld",&x,&y,&z);
b[i].x=x;
b[i].y=y;
b[i].z=z-a[x]-a[y];
}
sort(b+1,b+m+1,cmp);
int cnt=0;
ll ans=0;
fo(i,1,m)
{
int fx=find(b[i].x),fy=find(b[i].y);
if(fx!=fy)
{
f[fy]=fx;
ans+=b[i].z;
cnt++;
if(cnt==n-1) break;
}
}
cout<<ans;
}