ポータルの
アイデア:
間隔は0から目標値まで増加します。これは間隔目標値の最初のケースに相当し、毎回間隔を-1にし、最後に目標値をすべて0にします。その後、全体的なアイデアは最高点を下げることです。最初に、これまで待ちます。エッジで接続された2つのポイントの高さが同じである場合、それらを接続します。これにより、このエッジの重みとして、両側の2つのポイントの高さが低い方を見つけることができます(高さは下の方に下がります。2つはポイントが接続されている場合)、エッジの重みを大きいものから小さいとトラバースし、トラバーサルプロセス中に接続されたブロックを見つけてマージします(ポイントに抽象化されます。同じ高さであるということ)、重量が大きすぎるので、慎重に
コード:
#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;
}