洛谷2016 戰略遊戲 (0/1狀態的普通樹形Dp)
阿新 • • 發佈:2018-11-15
題意:
給出一個樹,覆蓋樹上某一個點的花費為w[i],求樹上每一條邊至少有一個點覆蓋的最小花費。
細節:
1.一條邊的兩端可以均被覆蓋,但是不能存在一條邊的兩端都不被覆蓋。
2.可能存在
分析:
對於一對兒子和父親節點來說,要麼兒子覆蓋父親不覆蓋,父親覆蓋兒子不覆蓋,或者是兩者均被覆蓋,所以不難發現對於父親節點來說,若其被覆蓋,則它的所有子孫可以被覆蓋也可以不被覆蓋,若其不被覆蓋,則它的子孫必須可以被全部覆蓋。
所以狀態變得顯然:dp[u][0/1] 表示節點 u 是否被覆蓋的最小花費
再根據上方的分析條件轉移如下:
dp[u][1] = ∑ min( dp[v][0] , dp[v][1] )
dp[u][0] = ∑ dp[v][1]
程式碼
#include<bits/stdc++.h> #define MAXN 1505 using namespace std; int f[MAXN][2], n; vector<int> Right[MAXN]; void dfs(int u, int fa){ f[u][0]=0, f[u][1]=1; for (int i=0; i<Right[u].size(); i++) { int v=Right[u][i]; if (v==fa) continue; dfs(v, u); f[u][0]+=f[v][1]; f[u][1]+=min(f[v][0], f[v][1]); } } int main(){ scanf("%d", &n); for (int i=1, x, num; i<=n; i++) { scanf("%d%d", &x, &num); for (int j=1, y; j<=num; j++) { scanf("%d", &y); Right[x].push_back(y); Right[y].push_back(x); } } dfs(1, -1); printf("%d\n", min(f[root][0], f[root][1])); return 0; }
Ps:
此題與 DAY2T3 的 44 分演算法十分雷同,但是我死在了考場的一線上……