• Atcoder Black Cats Deployment(树 + 并查集)


    链接:https://cf17-tournament-round3-open.contest.atcoder.jp/tasks/asaporo2_e

    题目大意:给定一颗有n个节点的树,每条边有一个权重c, 对于i,X表示对于所有j!=i,从i到j的路径上最小的c之和,求对于所有的i,X分别等于多少?

    分析:将所有边按权重排序从大到小,每次插入一条边,对于这条边两边的两个连通块A、B来说,路径上的最小权重都是c,所以对A中的点全部加c*|B|,对B也一样,即可得到答案。这样复杂度是O(n^2)的,合并点集用的是并查集,加一个add数组,使得i的答案是从i到祖先的路径上所有add之和,然后每次更新都是O(1)的,总复杂度为O(n)。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxn = 1e5 + 5;
     7 typedef long long ll;
     8 int p[maxn], n;
     9 ll add[maxn], cnt[maxn];
    10 struct Edge{
    11     int a, b;
    12     ll c;
    13 }e[maxn];
    14 bool Cmp(Edge a, Edge b){return a.c > b.c;}
    15 int Find(int x){
    16     if(p[x] == x)return x;
    17     if(Find(p[x]) == p[x])return p[x];
    18     add[x] += add[p[x]];
    19     p[x] = p[p[x]];
    20     //add[x] -= add[p[x]];
    21     return p[x];
    22 }
    23 void Merge(int a, int b, ll c){
    24     int x = Find(a), y = Find(b);
    25     add[x] += c * cnt[y];
    26     add[y] += c * cnt[x];
    27     cnt[x] += cnt[y];
    28     add[y] -= add[x];
    29     p[y] = x;
    30 }
    31 int main(){
    32 //    freopen("e:\in.txt","r",stdin);
    33     cin>>n;
    34     int a, b;
    35     ll c;
    36     for(int i = 0; i < n - 1; i++)scanf("%d%d%lld", &e[i].a, &e[i].b, &e[i].c);
    37     sort(e, e + n - 1, Cmp);
    38     for(int i = 1; i <= n; i++)p[i] = i, add[i] = 0, cnt[i] = 1;
    39     for(int i = 0; i < n - 1; i++){
    40         Merge(e[i].a, e[i].b, e[i].c);
    41     }
    42 //    for(int i = 1; i <= n; i++){
    43 //        cout<<p[i]<<' '<<add[i]<<endl;
    44 //    }
    45     for(int i = 1; i <= n; i++){
    46         Find(i);
    47 //        cout<<p[i]<<' '<<add[i]<<endl;
    48         ll ans;
    49         if(p[i] == i)ans = add[i];
    50         else ans = add[i] + add[p[i]];
    51         printf("%lld
    ", ans);
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    最大子序列和问题的几种算法
    给Repeater控件里添加序号的5种方法
    关于上传(上传所用到的upload和upload的应用)
    .net中的动态时钟 (年月日 时分秒)
    网页总结
    PHP算法将数字金额转换成大写金额
    Linux下编译安装redis,详细教程
    如何让PHP支持Redis
    网络互连技术——第一章随记
    网络互连技术——第二章考试需知
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7955216.html
Copyright © 2020-2023  润新知