[codevs1380]没有上司的舞会([BZOJ2060][Usaco2010 Nov]Visiting Cows 拜访奶牛)
[codevs1380]没有上司的舞会
试题描述
Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
输入
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。
输出
输出最大的快乐指数。
输入示例
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
输出示例
5
数据规模及约定
见“输入”
题解
我来刷水了!
把每个人看成一个节点。设 f[0][i] 表示对于子树 i,不选择 i 节点能够得到的最大值;f[1][i] 表示选择 i 节点能够得到的最大值。那么,
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); } return x * f; } #define maxn 6010 #define maxm 12010 int n, m, head[maxn], next[maxm], to[maxm], val[maxn]; void AddEdge(int a, int b) { to[++m] = b; next[m] = head[a]; head[a] = m; swap(a, b); to[++m] = b; next[m] = head[a]; head[a] = m; return ; } int f[2][maxn]; void dp(int u, int fa) { f[0][u] = 0; f[1][u] = val[u]; for(int e = head[u]; e; e = next[e]) if(to[e] != fa) { dp(to[e], u); f[0][u] += max(f[0][to[e]], f[1][to[e]]); f[1][u] += f[0][to[e]]; } return ; } int main() { n = read(); for(int i = 1; i <= n; i++) val[i] = read(); for(int i = 1; i < n; i++) { int a = read(), b = read(); AddEdge(a, b); } read(); read(); dp(1, 0); printf("%d\n", max(f[0][1], f[1][1])); return 0; }
双倍经验:BZOJ2060,改改输入。