当前位置:网站首页>2016CCPC网络选拔赛C-换根dp好题
2016CCPC网络选拔赛C-换根dp好题
2022-07-25 15:23:00 【塔子哥来了】
题目大意:
给一颗树,带点权和边权.问你每个点,得到的最大价值.(点权代表价值边权代表花费).每个点只能拿一次,边反复计算花费.
题目思路:
容易想出一种树形dp后换根的思路:
d p ( i , 0 / 1 ) dp(i,0/1) dp(i,0/1)代表以 i i i为根的子树,最后回到/不回到i点的最大价值.
d p ( i , 1 ) = ∑ j ∈ S o n i m a x ( d p ( j , 1 ) − 2 ∗ w i , 0 ) dp(i,1)=\sum_{j\in Son_i}max(dp(j,1)-2*w_i,0) dp(i,1)=∑j∈Sonimax(dp(j,1)−2∗wi,0)
d p ( i , 0 ) = d p ( i , 1 ) − m a x j ∈ S o n i ( m a x ( d p ( j , 0 ) − w i , 0 ) − m a x ( d p ( j , 1 ) − 2 ∗ w i , 0 ) ) dp(i,0)=dp(i,1)-max_{j\in Son_i}(max(dp(j,0)-w_i,0)-max(dp(j,1)-2*w_i,0)) dp(i,0)=dp(i,1)−maxj∈Soni(max(dp(j,0)−wi,0)−max(dp(j,1)−2∗wi,0))
下面令 g x 1 = m a x ( d p ( j , 1 ) − 2 ∗ w i , 0 ) , g x 2 = m a x ( d p ( j , 0 ) − w i , 0 ) gx_1=max(dp(j,1)-2*w_i,0),gx_2=max(dp(j,0)-w_i,0) gx1=max(dp(j,1)−2∗wi,0),gx2=max(dp(j,0)−wi,0)
再维护 s e ( i , 0 ) = d p ( i , 1 ) − 2 j ∈ S o n i t h ( m a x ( d p ( j , 0 ) − w i , 0 ) − m a x ( d p ( j , 1 ) − 2 ∗ w i , 0 ) ) se(i,0)=dp(i,1)-2^{th}_{j\in Son_i}(max(dp(j,0)-w_i,0)-max(dp(j,1)-2*w_i,0)) se(i,0)=dp(i,1)−2j∈Sonith(max(dp(j,0)−wi,0)−max(dp(j,1)−2∗wi,0))
和 t o ( i ) to(i) to(i)
(后面再讲这俩干嘛的)
转移完,考虑第二遍dfs,将父亲当作子树,把它的影响考虑进来
令新一轮的dp为 n d p , s s e , t t o ndp,sse,tto ndp,sse,tto
注意转移的时候要将父亲dp中对于该点的贡献取消,这个部分是最复杂的:
1.当更新 n d p ( i , 1 ) ndp(i,1) ndp(i,1)时,
父亲 f a fa fa对点 i i i的贡献 g x 3 = m a x ( n d p ( f a , 1 ) − g x 1 − w i , 0 ) gx_3=max(ndp(fa,1)-gx_1-w_i,0) gx3=max(ndp(fa,1)−gx1−wi,0)
那么 n d p ( i , 1 ) = d p ( i , 1 ) + g x 3 ndp(i,1)=dp(i,1)+gx_3 ndp(i,1)=dp(i,1)+gx3
n d p ( i , 0 ) = d p ( i , 0 ) + g x 3 ndp(i,0)=dp(i,0)+gx_3 ndp(i,0)=dp(i,0)+gx3 (先假设最后不留在父节点)
s s e ( i ) = s e ( i ) + g x 3 sse(i)=se(i)+gx_3 sse(i)=se(i)+gx3
2.当更新 n d p ( i , 0 ) ndp(i,0) ndp(i,0)时(most hard)
这个时候父亲节点对 i i i的贡献就很复杂了,分两种情况:
2.1当 d p ( f a , 0 ) dp(fa,0) dp(fa,0)最后不是落在子树 i i i时,父亲 f a fa fa对点 i i i的贡献 g x 4 = m a x ( n d p ( f a , 1 ) − g x 1 − w i , 0 ) gx_4=max(ndp(fa,1)-gx_1-w_i,0) gx4=max(ndp(fa,1)−gx1−wi,0)
2.2 否则,我们需要重新规划 d p ( f a , 0 ) dp(fa,0) dp(fa,0),让他最后的终点不要落在 i i i中。那么就落在哪?
次优解!
所以此时我们需要多维护 次优值 s e ( i ) se(i) se(i)和 最优值落在的儿子节点 t o ( i ) to(i) to(i) 用于判断是否落在子树.
那么贡献 g x 5 = m a x ( s s e ( f a , 1 ) − g x 1 − w i , 0 ) gx_5=max(sse(fa,1)-gx_1-w_i,0) gx5=max(sse(fa,1)−gx1−wi,0)
这时令 t m p = d p ( i , 1 ) + g x 4 / g x 5 − w tmp=dp(i,1)+gx_4/gx_5-w tmp=dp(i,1)+gx4/gx5−w
用 t m p tmp tmp来更新当前节点的最后留向
1.若 t m p ≥ n d p ( i , 0 ) tmp \geq ndp(i,0) tmp≥ndp(i,0) 代表往父亲节点走并留在那比(假设不往父亲节点走)更优,我们需要重新规划该点的 s s e , t t o sse,tto sse,tto
s s e ( i ) = n d p ( i , 0 ) , t t o = f a sse(i)=ndp(i,0),tto=fa sse(i)=ndp(i,0),tto=fa
2.否则无法更新.
PS:很久没写这么复杂的题目了。。不过还是独立完成了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int dp[maxn][2] , se[maxn] , f[maxn][2] , to[maxn] , a[maxn];
int tto[maxn] , sse[maxn];
vector<pii> e[maxn];
void dfs (int u , int fa){
dp[u][0] = dp[u][1] = 0;
for (auto &g : e[u]){
int v = g.first , w = g.second;
if (v == fa) continue;
dfs(v , u);
dp[u][1] += max(dp[v][1] - 2 * w , 0);
}
vector<pii> res;
for (auto &g : e[u]){
int v = g.first , w = g.second;
if (v == fa) continue;
int tmp = max(max(dp[v][0] - w , 0) - max(dp[v][1] - 2 * w , 0) , 0);
res.push_back({
tmp , v});
}
sort(res.begin() , res.end());
reverse(res.begin() , res.end());
if (res.size() > 0){
dp[u][0] = dp[u][1] + res[0].first;
to[u] = res[0].second;
if (res.size() == 1) se[u] = 0;
else se[u] = dp[u][1] + res[1].first;
}else {
se[u] = 0;
}
dp[u][0] += a[u];
dp[u][1] += a[u];
se[u] += a[u];
return ;
}
void dfs1 (int u , int fa , int ww){
f[u][0] = dp[u][0];
f[u][1] = dp[u][1];
tto[u] = to[u];
sse[u] = se[u] + max(w , 0);
int gx = max(0 , dp[u][1] - 2 * ww);
int w = f[fa][1] - gx - 2 * ww; // 选择fa并回来所带来的价值w
f[u][1] = dp[u][1] + max(w , 0);
f[u][0] = dp[u][0] + max(w , 0);
// 选择fa并不回来的价值ggg
int ggg;
if (tto[fa] == u) ggg = sse[fa] - gx - ww;
else ggg = f[fa][0] - gx - ww;
int ttt = dp[u][1] + max(ggg , 0);
// f[u][0] ttt
if (ttt >= f[u][0]){
sse[u] = f[u][0];
f[u][0] = ttt;
tto[u] = fa;
}else if (ttt >= sse[u]){
sse[u] = ttt;
}
for (auto &g : e[u]){
int v = g.first , w = g.second;
if (v == fa) continue;
dfs1(v , u , w);
}
return ;
}
int main()
{
ios::sync_with_stdio(false);
int t; cin >> t;
int cnt = 0;
while (t--){
int n; cin >> n;
for (int i = 1 ; i <= n ; i++){
e[i].clear();
tto[i] = sse[i] = dp[i][0] = dp[i][1] = se[i] = f[i][0] = f[i][1] = to[i] = 0;
}
for (int i = 1 ; i <= n ; i++) cin >> a[i];
for (int i = 1 ; i < n ; i++){
int x , y , z; cin >> x >> y >> z;
e[x].pb({
y , z});
e[y].pb({
x , z});
}
dfs (1 , 0);
dfs1(1 , 0 , 0);
cout << "Case #" << (++cnt) << ":" << endl;
for (int i = 1 ; i <= n ; i++){
cout << max(f[i][0] , f[i][1]) << endl;
}
}
return 0;
}
边栏推荐
- Submarine cable detector tss350 (I)
- Run redis on docker to start in the form of configuration file, and the connection client reports an error: server closed the connection
- My creation anniversary
- MySQL transactions and mvcc
- ML - 自然语言处理 - 关键技术
- Qtime定义(手工废物利用简单好看)
- Singleton mode 3-- singleton mode
- Single or multiple human posture estimation using openpose
- C#精挑整理知识要点9 集合2(建议收藏)
- Spark sql 常用时间函数
猜你喜欢

CF888G-巧妙字典树+暴力分治(异或最小生成树)

MySQL installation and configuration super detailed tutorial and simple database and table building method

获取键盘按下的键位对应ask码

matlab 如何保存所有运行后的数据

Idea remotely submits spark tasks to the yarn cluster

Overview of JS synchronous, asynchronous, macro task and micro task

Image cropper example

Use the command to check the WiFi connection password under win10 system

NPM's nexus private server e401 E500 error handling record

解决vender-base.66c6fc1c0b393478adf7.js:6 TypeError: Cannot read property ‘validate‘ of undefined问题
随机推荐
2021HNCPC-E-差分,思维
See a lot of blinking pictures on apps, especially the member page
Spark judges that DF is empty
SVD奇异值分解推导及应用与信号恢复
ML - 自然语言处理 - 自然语言处理简介
ML - Speech - advanced speech model
Spark-SQL UDF函数
Spark SQL common time functions
看到很多App出现闪烁的图片,特别是会员页面
Delayed loading source code analysis:
Example of password strength verification
记一次redis超时
苹果内购和Apple Pay 的区别
How much memory can a program use at most?
UIDocumentInteractionController UIDocumentPickerViewController
CGO is realy Cool!
ML - 语音 - 深度神经网络模型
Redis elimination strategy list
JVM dynamic bytecode technology details
wait()和sleep()的区别理解