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\n",ans); } return 0; }