题解:POI2012 Salaries
题解:POI2012 Salaries
Description
The Byteotian Software Corporation (BSC) has \(n\) employees.
In BSC's strict hierarchy, each employee has a direct supervisor, except the CEO, to whom all other BSC employees answer, directly or not.
Each employee has a unique monthly salary, and all their salaries range from 1 to \(n\) bythalers.
Each supervisor earns more than each of their subordinates.
According to Byteotian law, the salaries of employees on certain posts may be publicly disclosed.
Furthermore, if the salary of an employee is disclosed, then the salary of their supervisor is also disclosed.
The Byteotian Internal Revenue Anti-Corruption Service (BIRAS) has decided to investigate BSC.
Before BIRAS enters BSC with a warrant, they intend to learn the salaries of all BSC employees that are not disclosed but can be determined from those that are disclosed.
题意:
给一棵 \(n\) 个结点的树,点权取 \(1 \sim n\) 且 各不相同。
满足任意非根结点的权值一定比它的父节点权值小。
现在自顶向下地已知一些点的权值(即若某非根点权值已知,其父节点的权值也一定已知),
问哪些点的权值能唯一确定。
\(n \leq 1e6\)
Algorithm
这是一道 十分有趣 而 一言难尽 的题目。
我们先从两个例子入手,试图理解一下「唯一确定」的意思。
例一
在这里,由于点 \(b\) 是点 \(3\) 的孙子结点,最大只能取 \(1\) ,因此唯一确定 \(b = 1\)
同时,点 \(a\) 是点 \(3\) 的儿子结点,可能的取值有 \(1, 2\) ,但因为 \(b = 1\) ,所以唯一确定 \(a = 2\)
例二
此处 \(a, b\) 都是 \(3\) 的子节点,他们的取值可能为 \(1, 2\) ,但并不能唯一确定一种对应关系。
\(c\) 是 \(5\) 的子节点,可能的取值有 \(1, 2, 4\) 。但因为 \(a, b\) 对应 \(1, 2\) ,只能有 \(c = 4\) ,这也是唯一确定的。
揆诸上例与题面自顶向下给权的性质,我们容易发现:
对于任意一个未确定的结点,它的可能取值范围总是 \((0,x_i]\) ,
其中, \(x_i\) 是由树的结构与已知点权共同决定的。
一个点的权能被唯一确定,当且仅当其取值范围为 \((x_i - 1, x_i]\)
当我们确定了 \(k\) 个结点的取值后,剩余的未确定结点的取值范围就会变化为 \((k, x_i]\)
确定点权的顺序总是从小到大的。
(写成左开右闭的形式仅仅是为了规避区间左右端点相等的写法,没别的意思)
接下来只要模拟上述的推理即可。
我们可以首先一次 DFS 遍历整棵树,根据树结构维护每个点可能的最大取值。
特别注意此处有个坑,如果仅根据点的祖先结点取值和深度计算 \(x_i\) 的话代码就是错误的。
经过这种方法计算出的值 \(x'_i\) 可能已经被某个已知点取了,你需要尝试不断减少 \(x'_i\) 的值直到其符合定义为止。
这个"不断减少"的过程可以预处理出来。
DFS 之后,我们可以根据最大取值将点排序,再依次考虑每个权是否可以被确定或唯一确定。
这个算法描述起来还挺模糊的……不如直接读代码:
#include<bits/stdc++.h>
using namespace std;
template<class T>
inline void read(T &x)
{
char c = getchar(); x = 0;
while(c < '0' || '9' < c) c = getchar();
while('0' <= c && c <= '9')
{
x = (x << 1) + (x << 3) + c - 48;
c = getchar();
}
}
const int INF = 0x7f7f7f7f;
typedef pair<int, int> Node;
vector<Node> ord;
template<const int N, const int M>
class Tree {
private:
int beg[N], nex[M], tar[M], len;
public:
int vap[N], van[N];
bool vis[N];
Tree():len(1) {}
inline void add_egde(int a, int b)
{
++len, tar[len] = b;
nex[len] = beg[a], beg[a] = len;
}
void dfs(int cur, int val)
{
if(!vap[cur]) ord.push_back(Node(val, cur));
for(int i = beg[cur]; i; i = nex[i])
{
if(vap[tar[i]]) dfs(tar[i], vap[tar[i]]);
else dfs(tar[i], van[val - 1]);
}
}
};
Tree<1048576, 1048576> T;
int main()
{
int n, rot;
read(n);
for(int i = 1, x; i <= n; ++i)
{
read(x), read(T.vap[i]);
if(x == i) rot = i, T.vap[i] = n;
else T.add_egde(x, i);
if(T.vap[i])
T.vis[T.vap[i]] = true;
}
for(int i = 1; i <= n; ++i)
{
if(T.vis[i]) T.van[i] = T.van[i - 1];
else T.van[i] = i;
}
T.dfs(rot, n);
sort(ord.begin(), ord.end());
int done = 0, len = ord.size();
for(int i = 1, j = 0; i <= n; i++)
{
if(T.vis[i]) done++;
else
{
int cnt = 0;
while(j < len && ord[j].first == i) j++, cnt++;
if(cnt == 1 && done == i - 1)
T.vap[ord[j - 1].second] = i;
done += cnt;
}
}
for(int i = 1; i <= n; ++i)
printf("%d\n", T.vap[i]);
return 0;
}
题解:POI2012 Salaries的更多相关文章
- 【BZOJ2799】[Poi2012]Salaries 乱搞
[BZOJ2799][Poi2012]Salaries Description 给出一棵n个结点的有根树,结点用正整数1~n编号.每个结点有一个1~n的正整数权值,不同结点的权值不相同,并且一个结点的 ...
- [BZOJ2799][Poi2012]Salaries
2799: [Poi2012]Salaries Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 91 Solved: 54[Submit][Statu ...
- [POI2012]Salaries
题目大意: 给定一棵n带权树,每个点的权值在[1,n]范围内且互不相等,并满足子结点的权值一定小于父结点. 现在已知一个包含根结点的联通块中个点的权值,求剩下哪些点的权值能够被求出,并求出这些权值. ...
- bzoj 2799 [Poi2012]Salaries 性质+二分
题目大意 给出一棵n个结点的有根树,结点用正整数1~n编号. 每个结点有一个1~n的正整数权值,不同结点的权值不相同, 并且一个结点的权值一定比它父结点的权值小(根结点的权值最大,一定是n). 现在有 ...
- POI2012题解
POI2012题解 这次的完整的\(17\)道题哟. [BZOJ2788][Poi2012]Festival 很显然可以差分约束建图.这里问的是变量最多有多少种不同的取值. 我们知道,在同一个强连通分 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- [Poi2012]Festival 题解
[Poi2012]Festival 时间限制: 1 Sec 内存限制: 64 MB 题目描述 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1. 给出a,b (1 ...
- 【题解】 [POI2012]FES-Festival (差分约束)
懒得复制题面,戳我戳我 Question: (因为网上找不到好的翻译,这里简单复述一下) 告诉你\(m1+m2\)个约束条件,然后要你找出\(X_1-X_n\)这些数字,求满足要求的数列中不同的数字个 ...
- BZOJ2802: [Poi2012]Warehouse Store
2802: [Poi2012]Warehouse Store Time Limit: 10 Sec Memory Limit: 64 MBSec Special JudgeSubmit: 121 ...
随机推荐
- Kubernetes-12:Secret介绍及演示
Secret介绍 Secret存在的意义 Secret解决了密码.token.密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中,可以以Volume或者环境变量的方式使用 ...
- Vue的优缺点
使用vue.js做开发快两年了,对vue的优缺点有一点自己的见解,跟大神比不了,但是面试基本够用 vue在国内能被广泛使用的首要原因是它是基于mvvm框架做开发的,mvvm是前端开发中一种很有影响力的 ...
- PHP 类的构造方法 __construct()
1. 构造方法简介 构造方法 __construct() 是一种类结构特有的特殊方法,该方法由系统规定好 实例化一个类时:先调用该方法,再返回类的对象 构造方法也是普通方法,不同之处就是在实例化类时会 ...
- python appium app ui 自动化
1.下载Android-SDK.夜神安卓模拟器.Appium.adb命令执行包并配置环境变量 2.打开夜神 3.打开Appium进行配置,配置如下 4.启动命令,到夜神bin目录下执行 adb con ...
- “未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序”的解决方案
不论是连接Access数据库或是SQL Server数据库,"未在本地计算机上注册"Microsoft.ACE.OLEDB.12.0"提供程序."这个问题从Of ...
- 学习 | css3基本动画之demo篇
移动端使用的框架是zepto,但是zepto的内置对象没有传统的animate这个方法,效果都是需要css3来实现的,zepto也不支持fadeIn和fadeOut等一些基本的动画,基于这一现状,我自 ...
- CentOS 正在连接 127.0.0.1:8118... 失败:拒绝连接。
今天centos使用wget下载东西的时候出现了 看下是否开启了代理 yicunyiye@yicunyiye:~/redis$ export | grep -i proxy declare -x ft ...
- 20行代码实现,使用Tarjan算法求解强连通分量
今天是算法数据结构专题的第36篇文章,我们一起来继续聊聊强连通分量分解的算法. 在上一篇文章当中我们分享了强连通分量分解的一个经典算法Kosaraju算法,它的核心原理是通过将图翻转,以及两次递归来实 ...
- Docker镜像发布到阿里云
登录阿里云Docker Registry $ sudo docker login --username=xxx@xxx.com registry.cn-hangzhou.aliyuncs.com 从R ...
- java ThreadLocal理解和使用
一.ThreadLoal的理解 ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String ...