1 /* 2 题意:上司在,员工不在,反之不一定。每一个人有一个权值,问权值和最大多少。 3 树形DP:把上司和员工的关系看成根节点和子节点的关系,两者有状态转移方程: 4 dp[rt][0] += max (dp[son][1], dp[son][0]); //上司不去 5 dp[rt][1] += dp[son][0]; //上司去,员工都不去 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 #include <vector> 11 #include <cmath> 12 using namespace std; 13 14 const int MAXN = 6e3 + 10; 15 const int INF = 0x3f3f3f3f; 16 bool vis[MAXN]; 17 vector<int> edge[MAXN]; 18 int dp[MAXN][2]; 19 int n; 20 21 void DFS(int rt) 22 { 23 vis[rt] = true; 24 dp[rt][0] = 0; 25 for (int i=0; i<edge[rt].size (); ++i) 26 { 27 int son = edge[rt][i]; 28 if (!vis[son]) 29 { 30 DFS (son); 31 dp[rt][0] += max (dp[son][1], dp[son][0]); 32 dp[rt][1] += dp[son][0]; 33 } 34 } 35 } 36 37 int main(void) //URAL 1039 Anniversary Party 38 { 39 // freopen ("URAL_1039.in", "r", stdin); 40 41 while (scanf ("%d", &n) == 1) 42 { 43 memset (vis, false, sizeof (vis)); 44 memset (dp, 0, sizeof (dp)); 45 for (int i=1; i<=n; ++i) scanf ("%d", &dp[i][1]); 46 47 int l, k; 48 while (scanf ("%d%d", &l, &k) == 2) 49 { 50 if (l == 0 && k == 0) break; 51 vis[l] = true; 52 edge[l].push_back (k); 53 edge[k].push_back (l); 54 } 55 56 int root = 0; 57 for (int i=1; i<=n; ++i) 58 { 59 if (!vis[i]) {root = i; break;} 60 } 61 62 memset (vis, false, sizeof (vis)); DFS (root); 63 printf ("%d\n", max (dp[root][0], dp[root][1])); 64 } 65 66 return 0; 67 }
时间: 2024-10-08 01:11:23