CF1515F. Phoenix and Earthquake

题目描述

题解

如果 $\Sigma a_i < (n-1)x$ ,说明不可以。

否则证明其一定可以。

假设 $a_1 \le a_2 \le ... \le a_n$ ,则如果 $a_n+a_1<x$ ,则 $a_1 \le a_2 \le ... \le a_n <x-a_1$ ,则 $\Sigma a_i < (n-1)x-(n-2)a_1$ ,矛盾。因此我们可以每次让最大的和其相邻的任意一点合并即可。

代码

#include<bits/stdc++.h>
#define M make_pair
using namespace std;
#define LL long long
const int N=6e5+5;
int n,m,f[N],R[N],g[N],p[N],t[N];
LL a[N],X;
vector<pair<int,int>>e[N];
struct O{
    LL x;int u;
};
bool operator < (O A,O B){
    return A.x<B.x;
}
priority_queue<O>q;
int get(int x){
    return x==f[x]?x:f[x]=get(f[x]);
}
int main(){
    scanf("%d%d%lld",&n,&m,&X);
    for (int i=1;i<=n;i++)
        scanf("%lld",&a[i]),
        a[0]+=a[i],g[i]=p[i]=f[i]=i;
    for (int i=1,u,v;i<=m;i++)
        scanf("%d%d",&u,&v),
        t[u]++,t[v]++,
        e[u].push_back(M(v,i)),
        e[v].push_back(M(u,i));
    if (a[0]<X*(n-1)){puts("NO");return 0;}
    puts("YES");
    for (int i=1;i<=n;i++)
        q.push((O){a[i],i});
    while(!q.empty()){
        O u=q.top();q.pop();
        if (get(u.u)!=u.u) continue;
        int x=p[u.u];bool fl=1;
        while(fl && x){
            for (int i=t[x]-1,v;~i;i--){
                v=e[x][i].first;t[x]--;
                if (get(v)==u.u) continue;
                v=get(v);a[u.u]+=a[v]-X;
                printf("%d\n",e[x][i].second);
                R[g[u.u]]=p[v];g[u.u]=g[v];
                f[v]=u.u;fl=0;break;
            }
            if (fl) x=R[x],p[u.u]=x;
        }
        if (!fl) q.push((O){a[u.u],u.u});
    }
    return 0;
}

 

posted @ 2021-10-22 16:02  xjqxjq  阅读(27)  评论(0编辑  收藏  举报