https://codeforces.com/contest/1324/problem/F
reroot 첫 성공
<문제설명>
무방향트리가 주어진다. 각 정점마다 하얀색(1)또는 검은색(0)으로 색칠되어 있다.
i번 정점을 포함하는 서브트리 중 하얀색정점의 개수 - 검은색 정점의 개수가 최대인 경우 그 값을 각각 구해라 (i=1,2,3,4...n)
<풀이>
1번 정점을 root로 하는 전체 트리에서
dp[u] : u를 포함한 서브트리에서 cntw-cntb 최대값
u에 인접한 v에 대해 ans[v] = dp[v] + max(dp[u],0)이다.
v에서원하는 값 ans[v]가 u,v에대한 상태로만 정의되므로 reroot 적용가능하다.
dp[u] -= max(dp[v],0)
dp[v] += max(dp[u],0)
go(u,v)
dp[u] = memo1;
dp[v] = memo2;
백트래킹해주면된다.
<코드>
int n, dp[MAX], ans[MAX];
bool white[MAX];
vector<int> adj[MAX];
int makeDp(int u, int p) {
dp[u] = white[u] ? 1 : -1;
for (int v : adj[u]) if (v != p)
dp[u] += max(0, makeDp(v, u));
return dp[u];
}
void reroot(int u, int p) {
ans[u] = dp[u];
for (int v : adj[u]) if (v != p) {
int t1 = dp[u], t2 = dp[v];
dp[u] -= max(dp[v], 0);
dp[v] += max(dp[u], 0);
reroot(v, u);
dp[u] = t1;
dp[v] = t2;
}
}
int main() {
FAST; cin >> n;
for (int i = 1; i <= n; i++) cin >> white[i];
for (int i = 0, u, v; i < n - 1; i++) {
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
makeDp(1, 0);
reroot(1, 0);
for (int i = 1; i <= n; i++) cout << ans[i] << " \n"[i==n];
}
'알고리즘 > 코드포스' 카테고리의 다른 글
cf 626 div2 D - present (수론, 이분탐색) (0) | 2020.03.15 |
---|---|
cf 564 div2 D - Nauuo and circle (tree, graph dp) (0) | 2020.03.15 |
Educational #56 D - GCD counting (트리(숲) 지름, 소인수분해) (0) | 2020.03.13 |
codeforces 563 div2 D - Ehab and the Expected XOR Problem (XOR, prefix xor) (0) | 2020.01.29 |
Educational codeforces 67 div2 E - tree painting (dfs, dp, rerooting, tree) (0) | 2020.01.21 |