1. 程式人生 > >CodeForces 592D Super M DP

CodeForces 592D Super M DP

open href swa push_back vector con show 計算 isp

Super M

題解:

定義 dp[u][0] 為遍歷完u中的所有節點, 但不回到u點的路徑花費值。

定義 dp[u][1] 為遍歷完u中的所有節點, 且要回到u點的路徑花費值。

轉移方程.

dp[u][1] = sum(dp[v][1] + 2).

dp[u][0] = max(dp[v][1] + 2 - dp[v][0] - 1).

需要註意的是,不要把不需要走的路徑值傳遞上來。

只有這個路徑會遍歷一個需要清除的點的時候,才可以轉移狀態。

這樣從1dfs完之後,我們就可以計算出上面定義的狀態的值。

然後我們反著dfs一遍,就可以算出從每個點出發清除完所有點的值。

代碼:

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define
lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7
; const int N = 2e5 + 100; vector<int> vc[N]; LL dp[N][2]; /// 1->back 0-no-back LL dif[N][2]; /// dif[0] > dif[1] int vis[N]; int dfs(int o, int u){ for(int v : vc[u]){ if(o == v) continue; int f = dfs(u, v); if(!f) continue; LL t1 = dp[v][1] + 2; LL t2 = dp[v][0] + 1; t2 = t1 - t2; dp[u][1] += t1; if(dif[u][0] < t2) swap(t2, dif[u][0]); if(dif[u][1] < t2) swap(t2, dif[u][1]); } dp[u][0] = dp[u][1] - dif[u][0]; if(dp[u][1] == 0 && !vis[u]) return 0; return 1; } LL ans = INF, ansid; int fdfs(int o, int u){ if(o){ LL t1 = dp[o][1]; if(dp[u][1] || vis[u]) t1 -= (dp[u][1] + 2); if(t1 == 0 && !vis[o]) ; else { LL t2; LL now_dif = 0; if(dp[u][1] || vis[u]) now_dif= (dp[u][1]+2) - (dp[u][0]+1); if(now_dif == dif[o][0]) t2 = t1 - dif[o][1]; else t2 = t1 - dif[o][0]; t2 += 1; t1 += 2; dp[u][1] += t1; now_dif = t1 - t2; if(dif[u][0] < now_dif) swap(dif[u][0], now_dif); if(dif[u][1] < now_dif) swap(dif[u][1], now_dif); dp[u][0] = dp[u][1] - dif[u][0]; } } if(dp[u][0] < ans){ ans = dp[u][0]; ansid = u; } else if(dp[u][0] == ans && ansid > u) ansid = u; for(int v : vc[u]){ if(o == v) continue; fdfs(u, v); } return 0; } int main(){ int n, m; scanf("%d%d", &n, &m); int u, v; for(int i = 1; i < n; ++i){ scanf("%d%d", &u, &v); vc[u].pb(v); vc[v].pb(u); } for(int i = 1; i <= m; ++i){ scanf("%d", &u); vis[u] = 1; } dfs(0,1); fdfs(0,1); cout << ansid << "\n"<< ans << endl; return 0; }
View Code

CodeForces 592D Super M DP