1. 程式人生 > 其它 >CodeForces 767C :Garland 樹形DP

CodeForces 767C :Garland 樹形DP

技術標籤:DPcodeforces

傳送門

題目描述

n節點的樹,每個節點都有一個權值ti。
現在讓你恰好切掉其中的兩條邊,使得構成的新的3棵樹的權值和都變為一樣的。
即sum1=sum2=sum3.

分析

挺簡單的一個樹形DP,就是有個細節沒太注意一直wa
我們去求每一個節點的子樹的大小,如果大小等於sum/3就記錄答案,然後子樹大小置0
需要注意的是,我們只需要記錄兩個答案就可以了就比如我從根節點出發,已經刪減了兩棵子樹,這樣根節點形成的子樹的也是sum/3,但這個時候根節點也有可能被記錄,比如根節點的數值是0,這樣他的子樹大小也是滿足條件的,但是如果記錄這個節點,答案就不正確了

程式碼

#include
<iostream>
#include <cstdio> #include <cmath> #include <algorithm> #include <queue> #include <cstring> #define debug(x) cout<<#x<<":"<<x<<endl; #define _CRT_SECURE_NO_WARNINGS using namespace std; typedef long long ll; typedef unsigned
long long ull; typedef pair<int,int> PII; const int INF = 0x3f3f3f3f; const int N = 1e6 + 10; int a[N]; int dp[N]; int x1,x2; int h[N],ne[N * 2],e[N * 2],idx; int n; int sum; void add(int x,int y){ ne[idx] = h[x],e[idx] = y,h[x] = idx++; } void dfs(int u,int fa){ dp[u] = a[u]; for
(int i = h[u];~i;i = ne[i]){ int j = e[i]; if(j == fa) continue; dfs(j,u); dp[u] += dp[j]; if(dp[j] == sum / 3){ if(!x1) x1 = j; else (!x2) x2 = j; dp[u] -= dp[j]; } } } int main(){ memset(h,-1,sizeof h); scanf("%d",&n); int root; for(int i = 1;i <= n;i++){ int x,y; scanf("%d%d",&x,&y); a[i] = y; if(!x) root = i; else add(x,i),add(i,x); sum += y; } if(sum % 3){ puts("-1"); return 0; } dfs(root,-1); if(!x1 || !x2){ puts("-1"); return 0; } printf("%d %d\n",x1,x2); return 0; } /** *  ┏┓   ┏┓+ + * ┏┛┻━━━┛┻┓ + + * ┃       ┃ * ┃   ━   ┃ ++ + + + * ████━████+ * ◥██◤ ◥██◤ + * ┃   ┻   ┃ * ┃       ┃ + + * ┗━┓   ┏━┛ *   ┃   ┃ + + + +Code is far away from   *   ┃   ┃ + bug with the animal protecting *   ┃    ┗━━━┓ 神獸保佑,程式碼無bug  *   ┃        ┣┓ *   ┃        ┏┛ *  ┗┓┓┏━┳┓┏┛ + + + + *    ┃┫┫ ┃┫┫ *    ┗┻┛ ┗┻┛+ + + + */