2022 Nioke Winter Holiday Algorithm Basic Training Camp 2, Xiaosha's Magic

Portal
insert image description here
idea:

The interval increases from 0 to the target value, which is equivalent to the initial case of the interval target value, making the interval -1 each time, and finally making the target value all 0, then the overall idea is to drop the high point first, and then wait until this When the heights of the two points connected by the edge are the same, connect them, so we can find the one with the lower height of the two points on each side as the weight of this edge (when the height drops to the lower one, the two When the points are connected), sort the edge weights from large to small , traverse from large to small, find the connected block during the traversal process, and merge (abstract into a point, so that they have the same height), because the weight is too large, So just discretize

Code:

#include <bits/stdc++.h>
using namespace std;

const int maxn=5000000+50;
int n,m,T,a[maxn],sum[maxn],f[maxn];

struct node{
    
    
    int l,r,w;
}l[maxn];
long long ans;

bool cmp(node x,node y){
    
    
    return x.w>y.w;
}

int find(int x){
    
    
    if (f[x]==x) return x;
    return f[x]=find(f[x]);
}

int main(){
    
    
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; ++i)
        scanf("%d",&a[i]),f[i]=i;
        
    for (int i=1; i<=m; ++i){
    
    
        scanf("%d%d",&l[i].l,&l[i].r);
        l[i].w=min(a[l[i].l],a[l[i].r]);
    }
    sort(l+1,l+m+1,cmp);
    
    for (int i=1; i<=m; ++i){
    
    
        int f1=find(l[i].l),f2=find(l[i].r);
        if (f1==f2) continue;
        
        //各个连通块中非最小值与最小值的差分
        //差就是那个点需要减低到什么时候这条边才能相连
        ans+=max(a[f1],a[f2])-min(a[f1],a[f2]);
        a[f1]=a[f2]=min(a[f1],a[f2]);
        f[f1]=f2;
    }
    for (int i=1; i<=n; ++i)
    	//各个连通块中的最小值
        if (find(i)==i) ans+=a[i];
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45550375/article/details/122738930