传送门: https://codeforces.ml/contest/1263/problem/F
题意
给 两 棵 树 , 一 颗 在 上 面 , 另 一 颗 在 下 面 , 两 棵 树 的 叶 子 节 点 都 连 接 着 一 台 机 器 。 给两棵树,一颗在上面,另一颗在下面,两棵树的叶子节点都连接着一台机器。 给两棵树,一颗在上面,另一颗在下面,两棵树的叶子节点都连接着一台机器。
问 , 最 多 删 掉 多 少 条 边 , 每 个 机 器 都 至 少 存 在 一 条 路 径 到 达 两 个 根 节 点 1 中 的 一 个 。 问,最多删掉多少条边,每个机器都至少存在一条路径到达两个根节点1中的一个。 问,最多删掉多少条边,每个机器都至少存在一条路径到达两个根节点1中的一个。
思路
考
虑
d
p
,
设
d
p
[
i
]
表
示
前
i
个
机
器
通
电
的
最
大
删
除
边
数
。
考虑dp,设dp[i]表示前i个机器通电的最大删除边数。
考虑dp,设dp[i]表示前i个机器通电的最大删除边数。
设
v
a
l
[
0
/
1
]
[
L
]
[
R
]
表
示
上
/
下
树
中
区
间
[
L
,
R
]
最
大
删
除
边
数
。
设val[0/1][L][R]表示上/下树中区间[L,R]最大删除边数。
设val[0/1][L][R]表示上/下树中区间[L,R]最大删除边数。
即
转
移
方
程
为
:
即转移方程为:
即转移方程为:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
d
p
[
j
]
+
m
a
x
(
v
a
l
[
0
]
[
j
+
1
]
[
i
]
,
v
a
l
[
1
]
[
j
+
1
]
[
i
]
)
)
dp[i]=max(dp[i],dp[j]+max(val[0][j+1][i],val[1][j+1][i]))
dp[i]=max(dp[i],dp[j]+max(val[0][j+1][i],val[1][j+1][i]))
所 以 要 怎 么 处 理 这 个 v a l 呢 ? 所以要怎么处理这个val呢? 所以要怎么处理这个val呢?
在 树 上 处 理 , 第 一 想 到 的 就 是 d f s ! 在树上处理,第一想到的就是dfs! 在树上处理,第一想到的就是dfs!
因
为
叶
子
节
点
都
是
与
机
器
相
连
的
,
所
以
n
个
叶
子
节
点
类
似
于
线
段
的
端
点
。
因为叶子节点都是与机器相连的,所以n个叶子节点类似于线段的端点。
因为叶子节点都是与机器相连的,所以n个叶子节点类似于线段的端点。
对
于
每
个
子
树
,
都
会
有
一
个
端
点
区
间
,
当
删
除
该
子
树
时
,
该
区
间
内
的
机
器
无
法
到
达
根
节
点
。
对于每个子树,都会有一个端点区间,当删除该子树时,该区间内的机器无法到达根节点。
对于每个子树,都会有一个端点区间,当删除该子树时,该区间内的机器无法到达根节点。
删
除
该
子
树
后
,
贡
献
为
子
树
大
小
即
s
i
z
e
[
i
]
条
边
。
删除该子树后,贡献为子树大小即size[i]条边。
删除该子树后,贡献为子树大小即size[i]条边。
d f s 过 程 中 不 断 更 新 v a l [ L ] [ R ] 即 可 。 dfs过程中不断更新val[L][R]即可。 dfs过程中不断更新val[L][R]即可。
Code
#include "bits/stdc++.h"
using namespace std;
#define endl "\n"
#define eb emplace_back
#define mem(a, b) memset(a , b , sizeof(a))
const int N = 2e3 + 10;
int val[2][N][N];
int l[2][N], r[2][N];
vector<int> g[2][N];
int siz[N];
int dp[N];
void dfs(int u, int fa, int opt) {
if(u != 1) siz[u] = 1;
for(auto v : g[opt][u]) {
if(v == fa) continue;
dfs(v, u, opt);
siz[u] += siz[v];
l[opt][u] = min(l[opt][u], l[opt][v]);
r[opt][u] = max(r[opt][u], r[opt][v]);
}
val[opt][l[opt][u]][r[opt][u]] = max(val[opt][l[opt][u]][r[opt][u]], siz[u]);
}
void solve() {
int n; cin >> n;
mem(l, INF);
for(int i = 0;i < 2; i++) {
siz[1] = 0;
int a; cin >> a;
for(int j = 2;j <= a; j++) {
int u; cin >> u;
g[i][u].eb(j);
g[i][j].eb(u);
}
for(int j = 1;j <= n; j++) {
int v; cin >> v;
l[i][v] = j;
r[i][v] = j;
}
dfs(1, 0, i);
}
for(int i = 1;i <= n; i++) {
for(int j = 0;j < i; j++) {
dp[i] = max(dp[i], dp[j] + max(val[0][j + 1][i], val[1][j + 1][i]));
}
}
cout << dp[n] << endl;
}
signed main() {
solve();
}