BestCoder(Valentine's Day Round C题) hdu5176 The Experience of Love

来源:互联网 发布:贝多芬第五交响曲知乎 编辑:程序博客网 时间:2024/05/21 17:45

题意:给一棵树,求任意{两点路径上的(权值)最大边的权值-(权值)最小边的权值}的总和


思路:因为是树所以俩点间只有一条路径,把所有边排序,从小到大,一条边一条边的加,由于从小到大加边,所以因为加上此边后联通的俩点,此边就是这俩点之间路径的最大权值的边.假设边i,是链接a,b俩点的边。用带权并查集记录a,b分别相连的点数c,d。所以c*d*(i的权值)就是加i这条边时带来的价值.反之,求出再求出任意俩点间路径的最小边权值总和相减即可。

代码:

#pragma comment(linker, "/STACK:102400000,102400000")#include <stack>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;typedef unsigned long long ULL;template <class T>inline bool RD(T &ret){    char c; int sgn;    c = getchar(); if(c == EOF) return 0;    while(c!='-' && (c < '0' || c > '9')) c = getchar();    sgn = (c=='-')?-1:1; ret = (c=='-')?0:(c-'0');    while(c = getchar(), isdigit(c)) ret = ret*10+(c-'0');    ret *= sgn;return 1;}inline int RD() {int x; RD(x); return x;}template<class T> inline bool RD(T&x,T&y) {return RD(x)&&RD(y);}template<class T> inline bool RD(T&x,T&y,T&z) {return RD(x, y)&&RD(z);}const int MAXN = 150000+5;struct node{int x,  y,  z;}a[MAXN];int fa[MAXN];int cmp(node x, node y){return x.z < y.z;}int find(int x){if(fa[x] < 0){return x;}else return fa[x] = find(fa[x]);}void Union(int x, int y){int tx = find(x);int ty = find(y);if(tx == ty) return ;if(fa[tx] > fa[ty]) { fa[tx] += fa[ty]; fa[ty] = tx; }else { fa[ty] += fa[tx]; fa[tx] = ty; }}const int M = 6;const int base = 10000;struct Bignum{    int x[M];    Bignum(){}    Bignum(LL a){        memset(x, 0, sizeof(x));        for(int i=0; a>0; i++){            x[i] = a%base;            a/=base;        }    }    Bignum operator * (Bignum A){        Bignum C = Bignum(0);        for(int i=0; i<M; i++){            for(int j=0; i+j<M; j++){                C.x[i+j] += x[i] * A.x[j];            }        }        for(int i=0; i<M-1; i++){            C.x[i+1] += C.x[i]/base;            C.x[i]%=base;        }        return C;    }    Bignum operator + (Bignum A){        Bignum C = Bignum(0);        for(int i=0; i<M-1; i++){            C.x[i] = C.x[i] + x[i] + A.x[i];            if(C.x[i]>=10){                C.x[i+1] += C.x[i]/base;                C.x[i]%=base;            }        }        return C;    }    Bignum operator - (Bignum A){        Bignum C = Bignum(0);        for(int i=0; i<M; i++){            C.x[i] = C.x[i] + x[i] - A.x[i];            if(C.x[i]<0){                C.x[i] += base;                C.x[i+1]--;            }        }        return C;    }    void print(){        int i=M-1;        for(i; i>0; i--){            if(x[i])    break;        }        printf("%d", x[i]);        i--;        for(; i>=0; i--){            printf("%04d", x[i]);        }    }};int main(){    int n;     int w = 1;    while(~scanf("%d", &n))    {    for(int i = 0;i < n-1; ++i)    {    RD(a[i].x, a[i].y, a[i].z);    }    Bignum ans(0);    sort(a, a+n-1, cmp);    memset(fa, -1, sizeof(fa));    for(int i = 0;i < n-1; ++i)    {    int tx = -fa[find(a[i].x)];int ty = -fa[find(a[i].y)];ans = ans+Bignum(1ll*tx*ty*a[i].z);Union(a[i].x, a[i].y);    }    memset(fa, -1, sizeof(fa));    for(int i = n-2;i >= 0; --i)    {    int tx = -fa[find(a[i].x)];int ty = -fa[find(a[i].y)];ans = ans-Bignum(1ll*tx*ty*a[i].z);Union(a[i].x, a[i].y);    }    printf("Case #%d: ", w++); ans.print(); puts("");    }    return 0;}

后来发现根本不需要高精度,出题人只是故意卡了一下 long long,换成无符号的就好了(下面代码与上面的相同,只不过把高精度换成无符号了)

#pragma comment(linker, "/STACK:102400000,102400000")#include <stack>#include <cctype>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;typedef unsigned long long ULL;template <class T>inline bool RD(T &ret){    char c; int sgn;    c = getchar(); if(c == EOF) return 0;    while(c!='-' && (c < '0' || c > '9')) c = getchar();    sgn = (c=='-')?-1:1; ret = (c=='-')?0:(c-'0');    while(c = getchar(), isdigit(c)) ret = ret*10+(c-'0');    ret *= sgn;return 1;}inline int RD() {int x; RD(x); return x;}template<class T> inline bool RD(T&x,T&y) {return RD(x)&&RD(y);}template<class T> inline bool RD(T&x,T&y,T&z) {return RD(x, y)&&RD(z);}const int MAXN = 150000+5;struct node{int x,  y,  z;}a[MAXN];int fa[MAXN];int cmp(node x, node y){return x.z < y.z;}int find(int x){if(fa[x] < 0){return x;}else return fa[x] = find(fa[x]);}void Union(int x, int y){int tx = find(x);int ty = find(y);if(tx == ty) return ;if(fa[tx] > fa[ty]) { fa[tx] += fa[ty]; fa[ty] = tx; }else { fa[ty] += fa[tx]; fa[tx] = ty; }}int main(){    int n;     int w = 1;    while(~scanf("%d", &n))    {    for(int i = 0;i < n-1; ++i)    {    RD(a[i].x, a[i].y, a[i].z);    }    ULL  ans = 0;    sort(a, a+n-1, cmp);    memset(fa, -1, sizeof(fa));    for(int i = 0;i < n-1; ++i)    {    int tx = -fa[find(a[i].x)];int ty = -fa[find(a[i].y)];ans = ans+1ull*tx*ty*a[i].z;Union(a[i].x, a[i].y);    }    memset(fa, -1, sizeof(fa));    for(int i = n-2;i >= 0; --i)    {    int tx = -fa[find(a[i].x)];int ty = -fa[find(a[i].y)];ans = ans-1ull*tx*ty*a[i].z;Union(a[i].x, a[i].y);    }    printf("Case #%d: %I64u\n", w++, ans);    }    return 0;}



0 0