记录编号 33244 评测结果 AAAAAAAAAA
题目名称 火车站饭店 最终得分 100
用户昵称 Gravatarfanzeyi 是否通过 通过
代码语言 C 运行时间 0.882 s
提交时间 2011-11-09 20:40:06 内存使用 39.54 MiB
显示代码纯文本
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100010

int station[MAX];
int map[MAX][100];
int f[MAX], g[MAX];
int n;

// 以 station[0] 为根.. 开始搜索.. 
// 记忆化搜索
// f[x] 为 不选此节点
// g[x] 为 选择此节点做饭店
// f[x] = sum(max(g[x], f[x])) 
// g[x] = sum(f[x])

inline int max(int a, int b) {
    return a > b ? a : b;
}

void dp(int who, int father) {
    // 先把子节点的值都算出来
    if(map[who][0] == 1 && map[who][1] == father) {
        f[who] = 0;
        g[who] = station[who];
        return;
    }
    int i;
    for(i = 1; i <= map[who][0]; i++) {
        if(map[who][i] != father) {
            dp(map[who][i], who);
        }
    }
    // 开始计算 f[x] & g[x]
    for(i = 1; i <= map[who][0]; i++) {
        if(map[who][i] != father) {
            f[who] += max(g[map[who][i]], f[map[who][i]]);
            g[who] += f[map[who][i]];
        }
    }
}

int main(int argc, char const *argv[]) {
    FILE *fin = fopen("profitz.in", "r");
    FILE *fout = fopen("profitz.out", "w");
    int i, j;
    int x, y;
    memset(map, 0, sizeof(map));
    memset(f, 0, sizeof(f));
    memset(g, 0, sizeof(g));
    fscanf(fin, "%d", &n);
    for(i = 1; i <= n; i++) {
        fscanf(fin, "%d", &station[i]);
        g[i] = station[i];
    }
    for(i = 1; i <= n - 1; i++) {
        // 读入图 邻接表 map[*][0] 存储当前有多少条边..
        fscanf(fin, "%d %d", &x, &y);
        map[x][++map[x][0]] = y;
        map[y][++map[y][0]] = x;
    }
    dp(1, 0);
    fprintf(fout, "%d\n", max(f[1], g[1]));
    return 0;
}