CF1515F Phoenix and Earthquake

CF1515F Phoenix and Earthquake

证明题。

思路

考虑不合法的情况,如果 ai<(n1)×x,肯定是不合法的。

再考虑对于一个可行的情况,最后缩的边肯定形成一棵树,所以我们大胆假设:任意一棵生成树只要满足 ai(n1)×x 有合法的缩边方案。

考虑归纳证明:

n 个点的树中考虑叶子节点 u,其父亲为 v

  1. au<x,那么我们删除 (u,v) 这条边,由于所需总和 (n1)×x 减少了 x,而 ai 减少了 au,所以归纳假设任然成立。将边 (u,v) 加入栈。

  2. aux,那么我们把 auav 进行缩点,原树转化为 n1 个节点新树。将边 (u,v) 加入队列。

先使用队列输出边,再输出栈中的边

再给出这样的输出边的方案的正确性证明:

首先使用条件 2 中的边进行缩点,假设缩剩下了 t 个点,第 i 个点的点权为 ai

此时有 ai(t1)×x

其中仅可能包括根节点的 ai 大于 x;否则,可以进一步进行 2 操作的缩点,将满足 aix​ 的点缩到根节点处。

i>1ai<x,即 i>1xai1

不妨设根节点的缩点点权为 a1,有 a1i=2t(xai)

此时根节点可以与任意一个相连的缩点合并,不妨设该点为 ta1 肯定大于等于 xat),相当于不等式两边同时加了 atx,不等式仍然成立。

每次缩根节点和其相连的点就可以喽。

而我们根据栈输出的边正满足这样的条件,证明留给读者自行思考(doge)。

CODE

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

#define ll long long
#define pii pair<int,int>
#define F first
#define S second

const int maxn=3e5+5;

int n,m,x;
ll a[maxn];

vector<pii>E[maxn];

bool vis[maxn];

queue<int>que;
stack<int>stk;

inline void dfs(int u)
{
    vis[u]=true;
    for(auto v:E[u])
    {
        if(vis[v.F]) continue;
        dfs(v.F);
        if(a[v.F]>=x) que.push(v.S),a[u]+=a[v.F]-x;
        else stk.push(v.S);
    }
}

int main()
{
    ll sum=0;
    scanf("%d%d%d",&n,&m,&x);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i];
    if(sum<1ll*(n-1)*x){printf("NO");return 0;}
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        E[u].push_back({v,i}),E[v].push_back({u,i});
    }
    dfs(1);
    puts("YES");
    while(!que.empty()) printf("%d\n",que.front()),que.pop();
    while(!stk.empty()) printf("%d\n",stk.top()),stk.pop();
}
posted @   彬彬冰激凌  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示