HDU5242--Game DFS

来源:互联网 发布:为什么淘宝注册不了 编辑:程序博客网 时间:2024/05/05 22:18


点击打开题目链接

题意: n个点的以棵树, 每个点有一个权值。 每一次游戏从根出发一直走到叶子为止,不可从孩子往父亲走。 游戏可以进行k次, 每次经过一个点时会把这个点的权值加上, k次游戏中每个点只加一次。 输出k次游戏后, 经过的点总的最大的权值和。

比赛时,一直没想起来怎么做,一直在想DP的做法。赛后才知道不可以DP,是 一个贪心题目。

大致做法:

首先我们设dp[i] 表示 从 i点出发到它的叶子路径上权值和的最大值。 这一步显然一次DFS就可以了。

然后再来一次DFS, 从当前点出发, 每次首先选择它的孩子中dp[son]最大的走,这时 权值和加上 当前点的权值, 然后选择它的别的孩子,这一步怎么选都可以。

这样DFS后会 得到所有到叶子路径的和,而且每个点只计算了一次。 然后排序取前k个相加就是答案。。。

为什么比赛时没有想起来这么做呢。。。。大哭


#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int MAXN = 1e6+10;int n, k;struct Edge {    int to, next;} e[MAXN*2];int head[MAXN], tot_edge;void Add_Edge (int x, int y) {    e[tot_edge].to = y;    e[tot_edge].next = head[x];    head[x] = tot_edge++;}LL val[MAXN], dp[MAXN];LL ans[MAXN], ans_tot;void DFS1(int r, int pre) {    dp[r] = val[r];    for (int i = head[r]; ~i; i = e[i].next) {        int u = e[i].to;        if (u != pre) {            DFS1(u, r);            dp[r] = max(dp[r], val[r] + dp[u]);        }    }}void DFS (int r, int pre, LL pre_val) {    int flag = 0;    LL tmp = 0;    for (int i = head[r]; ~i; i = e[i].next) {        int u = e[i].to;        if (u != pre) {            if (dp[u] > tmp) {                flag = u;                tmp = dp[u];            }        }    }    for (int i = head[r]; flag && ~i; i = e[i].next) {        int u = e[i].to;        if (u != pre) {            if (u == flag) {                DFS(u, r, pre_val + val[u]);            } else {                DFS(u,r, val[u]);            }        }    }    if (!flag)        ans[ans_tot ++] = pre_val;}void init() {    memset(head, -1, sizeof (head));    ans_tot = tot_edge = 0;}int main() {#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);#endif    int T, cas = 1;    scanf ("%d", &T);    while (T--) {        init();        scanf ("%d%d", &n, &k);        for (int i = 0; i < n; i++) {            scanf ("%I64d", val+i+1);        }        for (int i = 0; i < n-1; i++) {            int u, v;            scanf ("%d%d", &u, &v);            Add_Edge(u, v);            Add_Edge(v, u);        }        DFS1(1, 0);        DFS(1, 0, val[1]);        sort (ans, ans+ans_tot);        LL res = 0;        for (int i = 0; i < k; i++) {            res += ans[ans_tot - i - 1];        }        printf("Case #%d: %I64d\n", cas++, res);    }    return 0;}


0 0
原创粉丝点击