codevs 1380 没有上司的舞会 - 树形动态规划

题目描述 Description

      Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

输入描述 Input Description

第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。

输出描述 Output Description

输出最大的快乐指数。

样例输入 Sample Input
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
样例输出 Sample Output
5 
数据范围及提示 Data Size & Hint

各个测试点1s


  按照这个关系建一棵树,然后进行树归,用f[i]表示i职员参加舞会的最大快乐指数之和,g[i]表示i职员不参加舞会的最大快乐指数之和。那么有f[i]为所有i的子节点的g[son[i]]的和,g[i]是i的子节点的g[son[i]]和f[son[i]]最大值的和。

  最后的答案在f[1]和g[1]中找最大值。

Code

  1 /**
  2  * codevs
  3  * Problem#1380
  4  * Accepted
  5  * Time:10ms
  6  * Memory:492k 
  7  */
  8 #include<iostream>
  9 #include<sstream>
 10 #include<algorithm>
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<cctype>
 15 #include<cmath>
 16 #include<ctime>
 17 #include<map>
 18 #include<stack>
 19 #include<set>
 20 #include<queue>
 21 #include<vector>
 22 #ifndef WIN32
 23 #define AUTO "%lld"
 24 #else
 25 #define AUTO "%I64d"
 26 #endif
 27 using namespace std;
 28 typedef bool boolean;
 29 #define inf 0xfffffff
 30 #define smin(a, b) (a) = min((a), (b))
 31 #define smax(a, b) (a) = max((a), (b))
 32 template<typename T>
 33 inline boolean readInteger(T& u) {
 34     char x;
 35     int aFlag = 1;
 36     while(!isdigit((x = getchar())) && x != '-' && x != -1);
 37     if(x == -1)    {
 38         ungetc(x, stdin);
 39         return false;
 40     }
 41     if(x == '-') {
 42         aFlag = -1;
 43         x = getchar();
 44     }
 45     for(u = x - '0'; isdigit((x = getchar())); u = u * 10 + x - '0');
 46     u *= aFlag;
 47     ungetc(x, stdin);
 48     return true;
 49 }
 50 
 51 typedef class Edge {
 52     public:
 53         int end;
 54         int next;
 55         Edge(const int end = 0, const int next = 0):end(end), next(next) {        }
 56 }Edge;
 57 
 58 typedef class MapManager {
 59     public:
 60         int ce;
 61         int *h;
 62         Edge *edge;
 63         MapManager():ce(0), h(NULL), edge(NULL)    {    }
 64         MapManager(int points, int edges):ce(0)    {
 65             h = new int[(const int)(points + 1)];
 66             edge = new Edge[(const int)(edges + 1)];
 67             memset(h, 0, sizeof(int) * (points + 1));
 68         }
 69         
 70         inline void addEdge(int from, int end) {
 71             edge[++ce] = Edge(end, h[from]);
 72             h[from] = ce;
 73         }
 74         
 75         Edge& operator [](int pos) {
 76             return edge[pos];
 77         }
 78 }MapManager;
 79 #define m_begin(g, i) (g).h[(i)]
 80 
 81 int n;
 82 int *val;
 83 MapManager g;
 84 int *f, *g1;
 85 int root;
 86 
 87 inline void init() {
 88     readInteger(n);
 89     val = new int[(const int)(n + 1)];
 90     g = MapManager(n, n);
 91     f = new int[(const int)(n + 1)];
 92     g1 = new int[(const int)(n + 1)];
 93     for(int i = 1; i <= n; i++)
 94         readInteger(val[i]);
 95     int sum = 0;
 96     for(int i = 1, a, b; i < n; i++) {
 97         readInteger(a);
 98         readInteger(b);
 99         sum += a;
100         g.addEdge(b, a);
101     }
102     root = n * (n + 1) / 2 - sum;
103 }
104 
105 void treedp(int node, int fa) {
106     g1[node] = 0;
107     f[node] = val[node];
108     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
109         int& e = g[i].end;
110         if(e == fa)    continue;
111         treedp(e, node);
112         g1[node] += max(g1[e], f[e]);
113         f[node] += g1[e];
114     }
115 }
116 
117 inline void solve() {
118     treedp(root, 0);
119     printf("%d", max(g1[root], f[root]));
120 }
121 
122 int main() {
123     init();
124     solve();
125     return 0;
126 }
posted @ 2017-03-23 19:31  阿波罗2003  阅读(252)  评论(0编辑  收藏  举报