标签:
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 145 Accepted Submission(s): 61
求树上任意两点路径上边权的 ( 最大值 - 最小值 ) 之和。
先排好序 , 用并查集,一条条边加进去 。 然后一条条边减掉 。
对于并查集 :
正确简洁的写法 , int find( int k ) { return fa[k] = ( k ==fa[k] ? k : find(fa[k])); }
少了fa[k]赋值的话会TLE。
然后这题会爆LL ,
对于ULL , 可以用 cout , %I64u , %llu 输出 。
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> #include <vector> #include <map> #include <vector> #include <queue> using namespace std ; typedef long long LL ; typedef unsigned long long ULL ; typedef pair<int,int> pii; #define X first #define Y second const int N = 150010; struct node { int u , v , w ; bool operator < ( const node &a )const { return w < a.w ; } }e[N]; int n , fa[N] ,cnt[N] ; void init() { for( int i = 1 ; i <= n ; ++i ) fa[i] = i , cnt[i]= 1 ; } int myfind( int k ) { return fa[k] = ( k == fa[k] ? k : myfind(fa[k]) ) ; } void solve() { init(); sort( e + 1 , e + n ); ULL sum = 0 , t = 1 ; for( int i = 1 ; i < n ; ++i ) { int fx = myfind( e[i].u ) , fy = myfind( e[i].v ); sum += 1ULL * cnt[fx] * cnt[fy] * e[i].w ; fa[fx] = fy ; cnt[fy] += cnt[fx] ; } init(); for( int i = n - 1 ; i >= 1 ; --i ) { int fx = myfind( e[i].u ) , fy = myfind( e[i].v ); sum -= 1ULL * cnt[fx] * cnt[fy] * e[i].w ; fa[fx] = fy ; cnt[fy] += cnt[fx] ; } printf("%llu\n",sum); } int main () { int _ , cas =1 ; while( ~scanf("%d",&n) ) { printf("Case #%d: ",cas++); for( int i = 1 ; i < n ; ++i ) { scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); } solve(); } }
HDU 5176 The Experience of Love
标签:
原文地址:http://www.cnblogs.com/hlmark/p/4292868.html