Description
Input
Output
Sample Input
4 1 2 2 2 4 1 2 3 1 4 1 2 1 2 4 1 2 3 1
Sample Output
4 3
思路:并查集,把边从大到小排,先放大的边,如果该边连接两个集合,那就判断哪个集合合并比较优,被合并的集合都通过新加边,最小的就是新加边。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define FOR(i,a,b) for(int i=a;i<=b;++i) #define clr(f,z) memset(f,z,sizeof(f)) #define LL long long using namespace std; const int mm=2e5+9; int rt[mm],rank[mm]; LL sum[mm]; class Edge { public:int a,b,c; bool operator<(const Edge&x)const { return c>x.c; } }e[mm]; void init(int n) { FOR(i,0,n)rt[i]=i,rank[i]=1,sum[i]=0; } int find(int x) { if(x^rt[x]) rt[x]=find(rt[x]); return rt[x]; } void uni(int a,int b,LL x) { a=find(a);b=find(b); LL ta,tb; ta=sum[a]+x*rank[b]; tb=sum[b]+x*rank[a]; if(ta>tb) rt[b]=a,rank[a]+=rank[b],sum[a]+=rank[b]*x; else rt[a]=b,rank[b]+=rank[a],sum[b]+=rank[a]*x; } int main() { int n,a,b,c; while(~scanf("%d",&n)) { init(n); FOR(i,2,n) { scanf("%d%d%d",&a,&b,&c); e[i].a=a;e[i].b=b;e[i].c=c; } sort(e+2,e+1+n); FOR(i,2,n) { uni(e[i].a,e[i].b,(LL)e[i].c); } printf("%I64d\n",sum[find(1)]); } }