【树DP】CF#551(div2)D
传送门
题意是每个节点有一个属性,取子树的最大或最小值。只有叶子节点有初始值,可以分别是1 – n(叶子节点个数)里面的任意一个值。问根节点最大值是多少。
很巧妙的思路。
对于每一个节点,在他及其子树中,相对大小都是确定了的。
比如在上图里。
节点{4}取最小,在{8, 9}里是第二大。
节点{2}取最大,在{8, 9, 5}里是第一大。
设f[i]表示i个节点的相对大小(第几大)。
对于每个节点,都需要尽量的大。所以f[i]需要尽量小。对于取\min的点,一定是子树的rank之和。而去\max的点,一定是子树的rank1.
最后拿总数减去根节点的rank就是根节点的取值
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 233;
vector<int> G[maxn];
int c[maxn], f[maxn], cnt;
void dfs(int x)
{
if(c[x]) f[x] = 1e9;
for(int i = 0; i < G[x].size(); i++)
{
int y = G[x][i];
dfs(y);
if(c[x]) f[x] = min(f[x], f[y]);
else f[x] += f[y];
}
if(!G[x].size()) f[x] = 1, cnt++;
}
int main()
{
int n ;
… Read the rest