tyvj1391走廊泼水节

题目:http://www.joyoi.cn/problem/tyvj-1391

考虑对于每一条边,新加的长度是(左边点数*右边点数-1)*(当前边权+1);

然后要kruskal的思想,把边从小到大加进去才能用上边的式子,因为保证了当前边两边的子图中没有大于当前边的边。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=6005;
int T,n,fa[N],siz[N],xnt;
ll ans;
struct Edge{
    int x,y;ll z;
    Edge(int x=0,int y=0,ll z=0):x(x),y(y),z(z) {}
}edge[N];
int find(int a)
{
    if(fa[a]==a)return a;
    return fa[a]=find(fa[a]);
}
bool cmp(Edge a,Edge b){return a.z<b.z;}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        ans=0;xnt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)fa[i]=i,siz[i]=1;
        int x,y;ll z;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%lld",&x,&y,&z);
            edge[++xnt]=Edge(x,y,z);
        }
        sort(edge+1,edge+xnt+1,cmp);
        for(int i=1;i<=xnt;i++)
        {
            x=edge[i].x;y=edge[i].y;z=edge[i].z;
            ans+=(siz[find(x)]*siz[find(y)]-1)*(z+1);
            siz[find(y)]+=siz[find(x)];
            fa[find(x)]=find(y);
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/8859343.html