24/05/08 图论

news/2024/10/4 15:24:36

\(\color{purple}(1)\) CF746G New Roads

  • 构造一棵 \(n\) 个点的深度为 \(t\) 的树,以 \(1\) 为根,使其中深度为 \(i\) 的点有 \(a_i\) 个且叶节点有 \(k\) 个。或报告无解。
  • \(t, k \le n \le 2 \times 10^5\)

为了方便,我们令根节点的深度为 \(1\)。所有读入都向后顺延一位。

首先计算这棵树最多和最少有几个叶子节点,那么如果 \(k\) 不在这个范围内则无解。那么模拟样例二:

第一个观察是无论如何构造,最后一层的节点一定是叶子节点,且第一层一定不是叶节点。

可以发现叶子最多的情况,是每一层的节点都连向上一层的同一个节点,即 \(k_{\max} = a_t + \sum_{i=1}^{t-1}\max(a_i - a_{i + 1}, 0)\)。叶子最少的情况,是每一层的节点都尽可能f多的连向上一层的不同的点,直到不能连为止,即 \(k_{\min} = a_t + \sum_{i=1}^{t-1} (a_i - 1)\)

除第一层外和最后一层外,每一层的叶子节点数一定不会少于 \(a_i - a_{i + 1}\)(如左图)且不会超过 \(a_i - 1\)(如右图)。那么我们可以处理出 \(b_2, b_3, \dots, b_{t - 1}\) 表示我们将要在第 \(i\) 层构造出 \(b_i\) 个叶子节点。需要保证 \(\max(0, a_i - a_{i + 1}) \le b_i \le a_i - 1\)\(\sum_{i=2}^{t-1} b_i = k - a_t\)。这是极易做到的。

然后考虑根据 \(b\) 数组构造整棵树。显然我们需要满足第 \(i\) 层中有 \(a_i - b_i\) 个点不是叶子节点,即连接至少一个下一层的点。那么直接模拟构造即可。

$\color{blue}\text{Code}$
int n, k, t, a[N], sum[N];int Id(int a, int b) {		// 第 a 层的第 b 个点return sum[a - 1] + b;
}int mn() {int res = a[t];for (int i = 1; i < t; ++ i )if (a[i] > a[i + 1]) res += a[i] - a[i + 1];return res;
}int mx() {int res = a[t];for (int i = 1; i < t; ++ i )res += a[i] - 1;return res;
}int b[N];
vector<pair<int, int> > res;void build_b() {int lst = k - a[t];for (int i = 2; i < t; ++ i ) {b[i] = max(0ll, a[i] - a[i + 1]);lst -= b[i];}for (int i = 2; i < t; ++ i ) {int tmp = min(lst, a[i] - 1 - b[i]);b[i] += tmp;lst -= tmp;}
}void Luogu_UID_748509() {fin >> n >> t >> k;++ t;sum[1] = 1;a[1] = 1;for (int i = 2; i <= t; ++ i ) fin >> a[i], sum[i] = sum[i - 1] + a[i];if (k < mn() || k > mx()) puts("-1");else {build_b();for (int i = 1; i < t; ++ i ) {int x = a[i] - b[i];for (int j = 1; j <= x; ++ j )res.emplace_back(Id(i, j), Id(i + 1, j));for (int j = x + 1; j <= a[i + 1]; ++ j )res.emplace_back(Id(i, x), Id(i + 1, j));}fout << n << '\n';for (auto t : res) fout << t.first << ' ' << t.second << '\n';}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/28930.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

2024-05-08:用go语言,给定一个由正整数组成的数组 nums, 找出数组中频率最高的元素, 然后计算该元素在数组中出现的总次数。 输入:nums = [1,2,2,3,1,4]。 输出:4。

2024-05-08:用go语言,给定一个由正整数组成的数组 nums, 找出数组中频率最高的元素, 然后计算该元素在数组中出现的总次数。 输入:nums = [1,2,2,3,1,4]。 输出:4。 答案2024-05-08: chatgpt 题目来自leetcode3005。 大体步骤如下: 1.创建一个空的字典 cnt 用于存储每个…

报错:Error: Cannot find module

报错详情: 解决方法: 1、正确安装版本号的nodejs 2、删除项目根文件夹下的node_modules和“package-lock.json”, 3、重新执行npm install

上课学习(无线网络)

考红色部分:如什么协议采用集中式架构CAPWAP优点,红色部分

2024CVPR_Low-light Image Enhancement via CLIP-Fourier Guided Wavelet Diffusion(CFWD)

一、Motivation 1、单模态监督问题:大多数方法往往只考虑从图像层面监督增强过程,而忽略了图像的详细重建和多模态语义对特征空间的指导作用。这种单模态监督导致不确定区域的次优重建和较差的局部结构,导致视觉结果不理想的出现。------》扩散模型缺乏有效性约束,容易出现…

Jmeter-线程组下篇

线程组 线程组作为JMeter测试计划的核心组件之一,对于模拟并发用户的行为至关重要。线程组元件是整个测试计划的入口,所有的取样器和控制器必须放置在线程组下。 可以将线程组视为一个虚拟用户池,其中每个线程可被理解为一个虚拟用户,多个虚拟用户同时执行相同的一批任务。…

字符串相关

字符串相关 文章参考: [详解-字符串] C++必知必会 字符串-string常用各种操作解析 - 知乎 (zhihu.com) C++ 字符串(string)常用操作总结 - 知乎 (zhihu.com) c++读取字符串和字符的6种函数_c++获取字符串的每个字符-CSDN博客 字符串使用大全(比较实用的):C++中的String的…

二分

二分 浮点数二分模板bool check(double x) {/* ... */} // 检查x是否满足某种特性double bsearch_3(double l, double r) {const double eps = 1e-6;while(r - l > eps){double mid = (l + r) / 2;if(check(mid)) r = mid;else l = mid;} return l; }整数二分模板bool chec…

【攻防技术系列+Python】-- 用 Python 控制系统进程

用 Python 控制系统进程 由于注册表几乎可以决定整个操作系统的运行,因此它成为安全工具与恶意软件对抗的主要战场之一。除了注册表之外,对系统进程的控制也是安全工具和恶意软件的必争之地。这里我们首先要了解程序和进程的区别。程序是静态的,进程是动态的。进程可以分为系…