【JZOJ4629】修路

Description

【JZOJ4629】修路_第1张图片

Solution

很显然,如果要取一条边 (u,v) ,那么贡献值就会增加 (au+av) ,于是我们把所有边的边权减去边两边端点的 ax ,然后我们会得到一些互不影响的边权,于是跑一次最小生成树即可。

Code

#include
#include
#include
#include
#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.zint 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<

你可能感兴趣的:(题解,最小生成树,数学其他)