https://www.luogu.com.cn/problem/P1352
开二维数组 dp[ Maxsize ][ 2 ]
dp[ i ][ 0 ] 表示上司 i 不参加舞会的最优解, dp[ i ][ 1 ]不参加舞会的最优解。
易得方程:dp[ i ][ 0 ] = 每一个孩子节点 x : dp[ i ][ 0 ] += max( dp[ x ][ 0 ] , dp[ x ][ 1 ]) ; dp[ i ][ 1 ] = 每一个孩子节点 x : dp[ i ][ 1 ] += max( 0, dp[ x ][ 0 ])
记得在初始化时对每一个 dp[ i ][ 1 ] 初始化为其本身的点权
由于我们可以用dp[ i ][ 1 ]记录点权(同时也是初始化的过程), 就不需要另外再开一个数组记录点权了,节省了空间。
1 #include <iostream> 2 #include <vector> 3 #define MAX(a,b) (a>b?a:b) 4 #define Maxsize 6000+1 5 using namespace std; 6 bool not_root[Maxsize]; 7 bool vis[Maxsize]; 8 int dp[Maxsize][2]; // dp[i][0] 不选用 i 的最优解 , dp[i][1] 选用 i 的最优解 9 vector<int> vec[Maxsize]; 10 void dfs(int root){ 11 for (auto it = vec[root].begin(); it != vec[root].end(); it++) { 12 if(!vis[*it]){ 13 vis[*it] = true; 14 dfs(*it); 15 vis[*it] = false; 16 } 17 } 18 for (auto it = vec[root].begin(); it != vec[root].end(); it++) { 19 if(vis[*it])continue; 20 dp[root][0] += MAX(dp[*it][0],dp[*it][1]); 21 dp[root][1] += MAX(dp[*it][0],0); 22 } 23 } 24 int main(){ 25 int n; 26 int a,b; 27 cin >> n; 28 for (int i = 1; i <= n; i++) { 29 cin >> dp[i][1]; 30 } 31 for (int i = 1; i <= n; i++) { 32 cin >> a >> b; // 子 , 父 33 vec[b].push_back(a); 34 not_root[a] = true; 35 } 36 int root = -1; 37 for (int i = 1; i <= n; i++) { 38 if(!not_root[i]){ 39 root = i; 40 break; 41 } 42 } 43 dfs(root); 44 cout << MAX(dp[root][0],dp[root][1]); 45 return 0; 46 }