题目链接:CF 或者 洛谷

首先基于一个事实,答案一定是生成树,显然,每次我们都需要连边,每次都会 \(-x\),那么一共会减少 \((n-1)\times x\),很显然的一个必要条件为:

\[\sum_{i=1}^{n}a_i \ge (n-1) \times x \ 显然一定成立。
\]

现在我们用来证明它同时也是一个充分条件,不妨设:

\[a_1 \le a_2 \le a_3\le a_4.... \le a_n,且\ \sum_{i=1}^{n}a_i \ge (n-1) \times x。
\]

假如无法找到 \(a_i+a_j \ge x\),不妨考虑极端情况,考虑与 \(a_n\) 相连的点 \(a_i\),假如有 \(a_i+a_n < x\),显然有 \(a_n<x-a_i\),所以此时有:

\[a_1 \le a_2 \le a_3...a_n < x-a_i,\sum_{i=1}^{n}a_i <(n-1)\times (x-a_i)+a_i
\]
\[\Rightarrow 原式<(n-1)\times x-(n-2)\times a_i,又知道\ n \ge 2,显然与条件矛盾。
\]

反证出我们一定能找到一组 \(a_i+a_j \ge x\)。我们将它取出,点数 \(-1\),总权减少了 \(x\):

\[\sum_{i=1}^{n-1}a_i \ge (n-2) \times x,显然又是一个同样的子问题。
\]

而 \(i=2\) 时,显然成立,所以这不仅是一个必要条件,同时还是个充分条件。

考虑构造的强结论

基于上述我们知道的充要条件,即满足那个式子以后,我们每次取出一对满足题意的点对,一定能构造出答案,现在我们来考虑不满足的情况,显然全部都 \(a_i \ge x\) 一定可以随意构造出答案,我们考虑不满足时有:

\[a_1 \le a_2 \le a_3....<x \le a_i \le a_{i+1}...\le a_n
\]

这个式子一定是成立的,否则找不到当前一对不满足题意的点,我们可以画出它的连边可能性图:

很显然,有三类可能性边:

  1. \(a_i,a_j \ge x\),这类显然满足题意。

  2. $a_i \ge x,a_j <x $,这类也显然满足题意。

  3. \(a_i,a_j <x\),这类可能和 \(\ge x\),也可能 \(<x\)。

我们其实只需要考虑 \(<x\) 的这种该如何通过其他边激活成功。我们考虑其他三类边对它的影响,很显而易见需要考虑的是如图中的 \(1-2\) 这条边。而激活一条边,把另一个点的点权减去 \(x\) 即 \(a_i-x\) 加到自身可能会使得变大变小,因为 \(a_i<x\) 或者 \(a_i>x\) 都有可能能激活边。

在讨论之前,我们需要明确一点,那就是答案是一棵生成树,当然 \(dfs 树\) 也行,考虑任意一棵都满足吗?答案是肯定的,基于充要条件,我们任意一棵树都可以至少找到一组点对,使得不断缩小为更小问题,那么很显然,我们从任意一棵生成树来讨论这三类边的影响:

如图所示,红色表示已经满足题意的可行边,蓝色表示不可行边(显然不可行边两个端点点权一定都 \(<x\)),当红色边激活后会使得某些蓝色边转化为红色边,然后再次重新激活红色边(当然也有可能某些红色边激活使得其他红色边变为了蓝色边),依次的进行激活所有边。

我们来考虑一个有意思的东西:

很显然叶子节点当除自身以外的所有边都激活时,一定会和剩下的连通块激活。举个例子,比如 \(6-3\) 这条蓝色边,当 \(3\) 与其他所有边除了 \(3-6\) 以外都变成红色了,那么 \(3-6\) 这条蓝色边一定可以变成红色边,基于充要条件。

加强结论:

对于例如 \(3\) 连接的所有叶子节点来说,当除了这些连边以外,与 \(3\) 连接的其他边变成红色以外,例如本图中即为 \(1-3\) 染成了红色以后,剩余的叶子节点边都能 “不计顺序” 地染成红色。

考虑反证法证明:

基于上述的三类边,显然当染色成红色边以后可大可小,大的情况为另一个和他染色的节点为 \(>x\),否则为 \(<x\)。而此时除了叶子节点以外对 \(3\) 已无影响,并且此时此刻的所有需要判断的叶子节点只有 “原本为” 蓝色边叶子节点,红色边我们已经能激活的全部激活了,所以这意味着这些剩余的叶子节点一定都是 \(<x\) 的,即对这个父节点影响是 “减小”,并不存在增大。

我们考虑依次操作叶子节点的影响,假如反复使得它变小,一直到某个叶子结点 \(a_i+a_3\) 无法染成红色,那显然这等价于无解,显然这个是不可能的,基于上述说的充要条件一定有解。所以叶子节点无论顺序,一定都能被染成红色边。

考虑子问题,把所有叶子节点放在最后一次染色,这等价于生成树少了一层,而其他情况就是正儿八经地能连就连,这样一来原图少一层就变为了:

这其实是一模一样的子问题(当然可能有蓝色边变为了红色边,而红色边变为了蓝色边,因为可大可小)。所以我们得到了最终的策略,从下往上贪心,每一层的叶子节点放在最后进行激活,能够激活的点优先激活,这样一来任意一棵 \(DFS\) 树我们都能正确地构造出答案了。

参照代码
#include <bits/stdc++.h>

// #pragma GCC optimize("Ofast,unroll-loops")
// #pragma GCC optimize(2) // #define isPbdsFile #ifdef isPbdsFile #include <bits/extc++.h> #else #include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/list_update_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/exception.hpp>
#include <ext/rope> #endif using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tii;
typedef tuple<ll, ll, ll> tll;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef __int128 i128;
#define hash1 unordered_map
#define hash2 gp_hash_table
#define hash3 cc_hash_table
#define stdHeap std::priority_queue
#define pbdsHeap __gnu_pbds::priority_queue
#define sortArr(a, n) sort(a+1,a+n+1)
#define all(v) v.begin(),v.end()
#define yes cout<<"YES"
#define no cout<<"NO"
#define Spider ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define MyFile freopen("..\\input.txt", "r", stdin),freopen("..\\output.txt", "w", stdout);
#define forn(i, a, b) for(int i = a; i <= b; i++)
#define forv(i, a, b) for(int i=a;i>=b;i--)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define endl '\n'
//用于Miller-Rabin
[[maybe_unused]] static int Prime_Number[13] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; template <typename T>
int disc(T* a, int n)
{
return unique(a + 1, a + n + 1) - (a + 1);
} template <typename T>
T lowBit(T x)
{
return x & -x;
} template <typename T>
T Rand(T l, T r)
{
static mt19937 Rand(time(nullptr));
uniform_int_distribution<T> dis(l, r);
return dis(Rand);
} template <typename T1, typename T2>
T1 modt(T1 a, T2 b)
{
return (a % b + b) % b;
} template <typename T1, typename T2, typename T3>
T1 qPow(T1 a, T2 b, T3 c)
{
a %= c;
T1 ans = 1;
for (; b; b >>= 1, (a *= a) %= c)if (b & 1)(ans *= a) %= c;
return modt(ans, c);
} template <typename T>
void read(T& x)
{
x = 0;
T sign = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')sign = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
x *= sign;
} template <typename T, typename... U>
void read(T& x, U&... y)
{
read(x);
read(y...);
} template <typename T>
void write(T x)
{
if (typeid(x) == typeid(char))return;
if (x < 0)x = -x, putchar('-');
if (x > 9)write(x / 10);
putchar(x % 10 ^ 48);
} template <typename C, typename T, typename... U>
void write(C c, T x, U... y)
{
write(x), putchar(c);
write(c, y...);
} template <typename T11, typename T22, typename T33>
struct T3
{
T11 one;
T22 tow;
T33 three; bool operator<(const T3 other) const
{
if (one == other.one)
{
if (tow == other.tow)return three < other.three;
return tow < other.tow;
}
return one < other.one;
} T3() { one = tow = three = 0; } T3(T11 one, T22 tow, T33 three) : one(one), tow(tow), three(three)
{
}
}; template <typename T1, typename T2>
void uMax(T1& x, T2 y)
{
if (x < y)x = y;
} template <typename T1, typename T2>
void uMin(T1& x, T2 y)
{
if (x > y)x = y;
} constexpr int N = 3e5 + 10;
ll sumA;
ll a[N];
int n, m;
int front, last; //前面放可以先激活的边,后面放下层的叶子节点连边
int ans[N];
vector<pii> child[N];
ll x;
bool vis[N]; inline void dfs(const int curr)
{
vis[curr] = true;
for (const auto [nxt,id] : child[curr])
{
if (vis[nxt])continue;
dfs(nxt);
if (a[curr] + a[nxt] >= x)a[curr] += a[nxt] - x, ans[front++] = id;
else ans[last--] = id;
}
} inline void solve()
{
cin >> n >> m >> x;
forn(i, 1, n)cin >> a[i], sumA += a[i];
forn(i, 1, m)
{
int u, v;
cin >> u >> v;
child[u].emplace_back(v, i);
child[v].emplace_back(u, i);
}
if (sumA < (n - 1) * x)
no << endl;
else
{
yes << endl;
front = 1, last = n - 1;
dfs(1);
forn(i, 1, n-1)cout << ans[i] << endl;
}
} signed int main()
{
// MyFile
Spider
//------------------------------------------------------
// clock_t start = clock();
int test = 1;
// read(test);
// cin >> test;
forn(i, 1, test)solve();
// while (cin >> n, n)solve();
// while (cin >> test)solve();
// clock_t end = clock();
// cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
}
\[时间复杂度为:\ O(n+m)
\]

CF1515F Phoenix and Earthquake 题解的更多相关文章

  1. [CF1515F] Phoenix and Earthquake(图论推导,构造)

    题面 在紧张又忙碌地准备联合省选时,发生了大地震,把原本要参赛的 n n n 个城市之间的全部 m m m 条道路震垮了,使得原本互相都能到达的这 n n n 个城市无法交通了.现在,需要紧急恢复 n ...

  2. 题解 CF1348D 【Phoenix and Science】

    题目大意,每天细菌会在早上选择分裂,晚上生长. 观察题目,我们可以发现.不管我们怎么分裂细菌,这一天晚上的总质量都是前一天晚上的总质量加上今天的细菌数. 那么我们肯定希望细菌分裂的越多越好,这样我们减 ...

  3. bzoj usaco 金组水题题解(2)

    续.....TAT这回不到50题编辑器就崩了.. 这里塞40道吧= = bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害 比较经典的最小割?..然而 ...

  4. bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

    1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害 Description Farmer John的农场里有P个牧场,有C条无向道路连接着他们,第i条道路连接着 ...

  5. Phoenix综述(史上最全Phoenix中文文档)

    个人主页:http://www.linbingdong.com 简书地址:http://www.jianshu.com/users/6cb45a00b49c/latest_articles 网上关于P ...

  6. 在DBeaver中phoenix查询报错:org.apache.phoenix.exception.PhoenixIOException: The system cannot find the path specified

    环境:Phoenix:4.4,win7系统 问题:Phoenix在查询hbase时,报"系统找不到指定路径". 解决: 请参见 https://distcp.quora.com/C ...

  7. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  8. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  9. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  10. HBase+Phoenix整合入门--集群搭建

    环境:CentOS 6.6 64位    hbase 1.1.15  phoenix-4.7.0-HBase-1.1 一.前置环境: 已经安装配置好Hadoop 2.6和jdk 1.7 二.安装hba ...

随机推荐

  1. AtCoder Regular Contest 123 (A~C 三道好题)

    比赛链接:Here A - Arithmetic Sequence (good) 注意细节 int main() { cin.tie(nullptr)->sync_with_stdio(fals ...

  2. 揭秘 vivo 如何打造千万级 DAU 活动中台 - 启航篇

    本文首发于 vivo互联网技术 微信公众号 链接:  https://mp.weixin.qq.com/s/Ka1pjJKuFwuVL8B-t7CwuA作者:悟空中台研发团队 vivo大厦(南京) 一 ...

  3. NodeJS开发服务端实现文件上传下载和数据增删改查

    本文主要讲解已NodeJS作为服务器完成文件的上传下载和数据增删改查,前端框架为Vue3,UI框架为element-plus,Node版本为V16.14.2. 项目场景模拟是开发一个项目管理的系统,支 ...

  4. jmap 查看jvm内存大小并进行dump文件内存分析

    本文为博主原创,未经允许不得转载: 1.jmap的使用 Jmap 可以用来查看内存信息,实例个数以及占用内存大小. jmap -histo[:live] 打印每个class的实例数目,内存占用,类全名 ...

  5. spring--Bean的作用域及应用场景

    这六种Spring Bean的作用域适用于不同的应用场景: Singleton: 在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在.无论我们是否在配置文件中显式定义,所有的S ...

  6. ABP微服务系列学习-微服务模板结构

    开源版本ABP CLI里面的模板是不包含微服务模板的,而商业版里面有一个微服务模板.这个模板据说是微服务的最佳实践,eShopOnAbp这个仓库的结构基本也和商业版的微服务模板一致.那就开始学习一下. ...

  7. [转帖]事务上的等待事件 —— enq: TX - contention

    TX锁是保护事务的,事务结束时便会释放.因此,为获得TX锁为等待的会话,要等到拥有锁的会话的事务结束为止. SQL> select name,parameter1,parameter2,para ...

  8. [转帖]Jmeter脚本录:抓取https请求

    Jmeter抓取http请求 https://blog.csdn.net/qq19970496/article/details/86595109 代理设置步骤请参照该篇文章.本文件只做补充HTTPS中 ...

  9. [转帖]jmeter_采样器sampler简介

    1.取样器介绍 取样器是用来模拟用户操作的,向服务器发送请求以及接收服务器的响应数据. 取样器是在线程组内部的元件,也就是说取样器只能在线程组中添加. 取样器(Sampler)是性能测试中向服务器发送 ...

  10. [转帖] Linux命令拾遗-使用blktrace分析io情况

    https://www.cnblogs.com/codelogs/p/16060775.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 一般来说,想检 ...