【算法练习】CodeForces915F Imbalance Value of a Tree (并查集)

题意

求出树上所有路径的最大值和最小值之差的和。

题解

套路题,考虑每个点对答案的贡献,把删点变成加点,遍历一遍就OK。

代码

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax],fa[nmax],sz[nmax],tot,n;
ll ans;
bool visit[nmax];
struct Node {
    int id; ll val;
}node[nmax];
struct edge{
    int to,nxt;
}e[nmax<<1];
int findset(int x){
    int rt = x, temp;
    while(fa[rt] != rt) rt = fa[rt];
    while(x != rt){
        temp = fa[x];
        fa[x] = rt;
        x = temp;
    }
    return rt;
}
void add(int u, int v){e[tot].to = v , e[tot].nxt = head[u], head[u] = tot++;}
bool cmp(Node a, Node b){return a.val > b.val;}
void getans(Node & u){
    for(int i = head[u.id];i!=-1;i = e[i].nxt){
        int v = e[i].to; v = findset(v);
        if(!visit[v]) continue;
        else{
            ans += 1ll * sz[u.id] * sz[v] * u.val;
            fa[v] = u.id; sz[u.id] += sz[v];
        }
    }
    u.val = -u.val;
}
int main(){
    memset(head,-1,sizeof head);
    scanf("%d",&n);
    for(int i = 1;i<=n;++i){
        fa[i] = i, sz[i] = 1;
        scanf("%I64d",&node[i].val);
        node[i].id = i;
    }
    int u,v;
    for(int i = 1;i<n;++i){
        scanf("%d %d",&u,&v);
        add(u,v), add(v,u);
    }
    sort(node+1,node+1+n,cmp);
    for(int i = n;i>=1;--i){
        getans(node[i]);
        visit[node[i].id] = true;
    }
    for(int i = 1;i<=n;++i) visit[i] = false, sz[i] = 1, fa[i] = i;
    for(int i = 1;i<=n;++i){
        getans(node[i]);
        visit[node[i].id] = true;
    }
    printf("%I64d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/81475477