zoukankan      html  css  js  c++  java
  • hdu5176(并查集)

    传送门:The Experience of Love

    题意:一个叫Gorwin的女孩和一个叫Vivin的男孩是一对情侣。他们来到一个叫爱情的国家,这个国家由N个城市组成而且只有N1条小道(像一棵树),每条小道有一个值表示两个城市间的距离。他们选择两个城市住下,Gorwin在一个城市Vivin在另外一个,第一次约会,Gorwin去找Vivin,她会写下路径上最长的一条小道(maxValue),第二次约会,Vivin去找Gorwin,他会写下路径上最短的一条小道(minValue),然后计算maxValue减去minValue的结果作为爱情经验值,再然后重新选择两个城市居住而且计算新的爱情经验值,重复一次又一次。当他们选择过所有的情况后,请帮助他们计算一下爱情经验值的总和。

    分析:sigma(maxVal[i]minVal[i])=sigma(maxVal)sigma(minVal);所以我们分别求所有两点路径上的最大值的和,还有最小值的和。再相减就可以了。求最大值的和的方法用带权并查集,把边按权值从小到大排序,一条边一条边的算,当我们算第i条边的时候权值为wi,两点是ui,vi,前面加入的边权值一定是小于等于当前wi的,假设与ui连通的点有a个,与vi连通的点有b个,那么在a个中选一个,在b个中选一个,这两个点的路径上最大值一定是wi,一共有ab个选法,爱情经验值为abwi求最小值的和的方法类似。

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <limits.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 100000000
    #define inf 0x3f3f3f3f
    #define eps 1e-6
    #define N 200010
    #define FILL(a,b) (memset(a,b,sizeof(a)))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define PII pair<int,int>
    #pragma comment(linker,"/STACK:1024000000,1024000000")
    using namespace std;
    int num[N],fa[N],n;
    inline int read() {
        int x=0; char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    struct edge
    {
        int u,v,w;
    }e[N];
    int cmp1(edge a,edge b)
    {
        return a.w<b.w;
    }
    int cmp2(edge a,edge b)
    {
        return a.w>b.w;
    }
    void init()
    {
        for(int i=1;i<=n;i++)fa[i]=i,num[i]=1;
    }
    int find(int x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    int main()
    {
        int cas=1;
        while(scanf("%d",&n)>0)
        {
            for(int i=1;i<n;i++)
            {
                e[i].u=read();
                e[i].v=read();
                e[i].w=read();
            }
            init();sort(e+1,e+n,cmp1);
            unsigned long long maxsum=0,t=1;
            for(int i=1;i<n;i++)
            {
                int pa=find(e[i].u);
                int pb=find(e[i].v);
                if(pa==pb)continue;
                maxsum+=t*num[pa]*num[pb]*e[i].w;
                fa[pa]=pb;
                num[pb]+=num[pa];
            }
            unsigned long long minsum=0;
            init();sort(e+1,e+n,cmp2);
            for(int i=1;i<n;i++)
            {
                int pa=find(e[i].u);
                int pb=find(e[i].v);
                if(pa==pb)continue;
                minsum+=t*num[pa]*num[pb]*e[i].w;
                fa[pa]=pb;
                num[pb]+=num[pa];
            }
            printf("Case #%d: ",cas++);
           cout<<maxsum-minsum<<endl;
        }
    }
    View Code
  • 相关阅读:
    # 2018-2019-1 20165206 《信息安全系统设计基础》第1周学习总结
    20165206 2017-2018-2《Java程序设计》课程总结
    2017-2018-2 20165206 实验五《网络编程与安全》实验报告
    20165206第4次实验《Android程序设计》实验报告
    同源策略、跨域解决方案
    盒子模型,块级元素和行内元素
    http常见错误
    深入理解 JavaScript 事件循环(一)— event loop
    git常用指令
    js 常用方法
  • 原文地址:https://www.cnblogs.com/lienus/p/4292262.html
Copyright © 2011-2022 走看看