版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/try__jhf/article/details/82596211
题目大意
见题目……
解题报告
完全不会做啊……
从边入手这道题.
把每条边所连的左右两个点分别看做一个集合,左边集合和右边集合所要连的边数是(cnt[i]*cnt[j]-1)。
但我们要连的边权是多大?不能比当前的边还小,所以边权就为(当前边的边权+1),我们可以贪心的去解决,把边从小到大排序,并查集一下就行了,当然还得加上原始边的边权。
全是抄的……
示例代码
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100005;
int n,fa[maxn],cnt[maxn];
LL ans;
struct data{
int x,y,z;
data (int x=0,int y=0,int z=0):x(x),y(y),z(z){}
bool operator < (const data b)const{return z<b.z;}
}a[maxn];
inline void readi(int &x){
x=0; char ch=getchar();
while ('0'>ch||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
}
int getf(int x){return (fa[x]==x)?x:fa[x]=getf(fa[x]);}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
readi(n); ans=0;
for (int i=1,x,y,z;i<n;i++){
readi(x); readi(y); readi(z);
a[i]=data(x,y,z); ans+=z;
}
sort(a+1,a+n); for (int i=1;i<=n;i++) {fa[i]=i; cnt[i]=1;}
for (int i=1,fx,fy;i<n;i++){
fx=getf(a[i].x); fy=getf(a[i].y);
ans+=(LL)(a[i].z+1)*((LL)cnt[fx]*cnt[fy]-1);
fa[fy]=fx; cnt[fx]+=cnt[fy];
}
printf("%lld",ans);
return 0;
}