zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    《数据结构第一章复习》
    《图的基本操作》
    《矩阵的一些基本操作》
    <矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置>
    《两个二维数组(矩阵)相乘》
    C#隐藏与显示系统任务栏和开始菜单栏按钮
    C#通过窗体属性缩小一定尺寸时,无法再缩小窗体尺寸问题
    C#一个窗体调用另一个窗体的方法
    C#异步线程
    C#中MessageBox.Show问题(让提示窗口不显示在任务栏中)
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7955216.html
Copyright © 2011-2022 走看看