1. 程式人生 > >【題解】Atcoder ARC#83 E-Bichrome Tree

【題解】Atcoder ARC#83 E-Bichrome Tree

兩個 白色 bit 顏色 etc 色相 ret last chrome

  哈哈~自己做出來的E題!(雖然這題被機房大佬強D極水)。最開始神經錯亂,寫了個完全不對的貪心,竟然只錯了4個點(?•ˇ?ˇ•?)

  可以發現,一個節點的子樹內部和他顏色相同的節點權值和 是固定的,那麽不一定的就是另外的那個顏色的權值和了。而由於這個圖上權值可以從 0 開始取值,顯然越小越好。這樣就可以dp啦。

  其實我這個裏面多了一個維度,就是記錄當節點為黑色/白色時怎麽怎麽樣,但其實這兩個狀態完全對稱,根本沒必要再多開一個維。但我就懶得改啦~

#include <bits/stdc++.h>
using namespace std;
#define
maxn 6000 #define INF 999999999 int n, W[maxn], f[2][2][maxn], g[maxn][2]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); } while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar();
return x * k; } struct edge { int cnp, to[maxn], last[maxn], head[maxn]; edge() { cnp = 2; } void add(int u, int v) { to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++; } }E1; bool Down(int &x, int y) { if(y >= INF) return 0; x = min(x, y); return 1; }
void dfs(int u) { for(int i = E1.head[u]; i; i = E1.last[i]) { int v = E1.to[i]; dfs(v); } for(int i = 0; i <= 1; i ++) for(int j = 0; j <= W[u]; j ++) f[0][i][j] = INF; f[0][0][0] = f[0][1][0] = 0; int pre = 0, now = 1; for(int i = E1.head[u]; i; i = E1.last[i]) { int v = E1.to[i]; for(int j = 0; j <= 1; j ++) for(int k = 0; k <= W[u]; k ++) f[now][j][k] = INF; for(int k = 0; k <= 1; k ++) for(int j = 0; j <= W[u]; j ++) { int flag = 0; if(j - W[v] >= 0) flag = Down(f[now][k][j], f[pre][k][j - W[v]] + g[v][k]); if(j - g[v][k ^ 1] >= 0) flag = Down(f[now][k][j], f[pre][k][j - g[v][k ^ 1]] + W[v]); } swap(pre, now); } g[u][0] = g[u][1] = INF; for(int k = 0; k <= 1; k ++) for(int j = 0; j <= W[u]; j ++) g[u][k] = min(g[u][k], f[pre][k][j]); } int main() { n = read(); for(int i = 2; i <= n; i ++) { int x = read(); E1.add(x, i); } for(int i = 1; i <= n; i ++) W[i] = read(); dfs(1); if(g[1][0] < INF || g[1][1] < INF) printf("POSSIBLE\n"); else printf("IMPOSSIBLE\n"); return 0; }

【題解】Atcoder ARC#83 E-Bichrome Tree