Description
抽象题意:每条边有代价,每个点被连了以后有贡献,求最小生成树的最小的代价。
Solution
每个点被连了以后有贡献,也就是连他们的边代价会减少,
把边的代价减两个点的
ai
以后做一遍最小生成树即可。
复杂度:
O(nlog(n))
Code
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long LL;
const int N=100500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m;
LL ans;
int a[N],g[N];
struct qqww
{int x,y;LL v;}b[N];
bool PX(qqww q,qqww w){return(q.v<w.v);}
int gf(int q){return g[q]=(g[q]!=q?gf(g[q]):q);}
int main()
{
int q;
read(n),read(m);
fo(i,1,n)read(a[i]),g[i]=i;
fo(i,1,m)read(b[i].x),read(b[i].y),b[i].v=read(q)-a[b[i].x]-a[b[i].y];
sort(b+1,b+1+m,PX);
q=0;
fo(i,1,m)
{
int x=gf(b[i].x),y=gf(b[i].y);
if(x!=y)ans+=b[i].v,q++,g[y]=x;
if(q+1==n)break;
}
printf("%lld\n",ans);
return 0;
}