ZOJ2834--Maximize Game Time(树形DP)

写之前觉得很恶心,写完了觉得挺好玩了,1A,棒棒哒~

题解全在代码注释中了,想清楚思路一路写下了果然没怎么卡 ^_^

/*******************************************************
Memory: 316 KB		Time: 0 MS
Language: C++ (g++ 4.7.2)		Result: Accepted
*******************************************************/
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <complex>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cassert>
using namespace std;
#define PI acos(-1.0)
#define EXP exp(1.0)
#define ESP 1E-6

/**
什么恶心题!话说最后还是想不到一点无耻的看了别人的题解,竟然是暴力orz,暴力出奇迹。。果然还是太弱啊啊啊啊!

思路基本自己想的,突然觉得图论挺好玩的嘛~~

题意:n个怪物0~n-1,打死每个怪物有一个时间,怪物家族的结构是一个树形。其中n-1一定是根。如果要打死一个怪物的两个儿子,
      那么就需要打死该怪物。打死怪物n-1游戏立即结束。求最长的游戏时间。

想法:这个树形结构的家族可能是一个森林。对于根不是n-1的树,全部杀死。对于n-1,杀光一颗子树,杀掉一个子儿子,
      该儿子处理方式同n-1,其他儿子全部不能杀死,意味着其他儿子的儿子只能杀死一个。。。
*/

const int N = 1005;

int T[N];
vector<int> G[N];
int root[N];

int sz[N];
int one[N];
int ans[N];

int n;

// 求每个结点子树时间和(包括该点)
void dfs_sz(int v)
{
    sz[v] = T[v];
    for (unsigned i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        dfs_sz(u);
        sz[v] += sz[u];
    }
}

// 我觉得我的名字起得特别棒(不包括该节点
void dfs_one_son(int v)
{
    if (one[v] != -1) return ;
    int temp = 0;
    int tol = 0;
    for (unsigned i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        dfs_one_son(u);
        tol += one[u];
    }
    for (unsigned i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        temp = max(temp, tol - one[u] + sz[u]);
    }
    one[v] = temp;
}

void dfs_solve(int v)
{
    if (ans[v] != -1) return ;
    int temp = 0;
    int tol = 0;

    if (G[v].size() == 0)
    {
        ans[v] = T[v];
        return ;
    }
    if (G[v].size() == 1)
    {
        int u = G[v][0];
        dfs_solve(u);
        ans[v] = ans[u] + T[v];
        return ;
    }

    for (unsigned i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        dfs_solve(u);
        tol += one[u];
    }
    for (unsigned i = 0; i < G[v].size(); ++i) // 我看别人的代码就是这里。。就一眼。。没想到用两层循环。。。
    {
        int u = G[v][i];
        for (unsigned j = 0; j < G[v].size(); ++j)
        {
            if (i == j) continue;
            int k = G[v][j];
            temp = max(temp, tol - one[u] - one[k] + sz[u] + ans[k]);
        }
    }
    //printf("temp=%d,T[%d]=%d\n", temp, v, T[v]);
    ans[v] = temp + T[v];
}

int main()
{
    while (~scanf("%d", &n) && n)
    {
        /// initialize
        memset(one, -1, sizeof one);
        memset(ans, -1, sizeof ans);
        for (int i = 0; i <= n; ++i) G[i].clear();

        /// input
        for (int i = 0; i < n; ++i)
            scanf("%d", &T[i]);
        int a;
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", &a);
            root[i] = a;
            G[a].push_back(i);
        }

        /// solve
        int res = 0;
        for (int i = 0; i < n - 1; ++i)
            if (root[i] == -1)
            {
                dfs_sz(i);
                res += sz[i];
            }

        dfs_sz(n - 1);
        dfs_one_son(n - 1);
        dfs_solve(n - 1);

        res += ans[n - 1];

        printf("%d\n", res);

//        for (int i = 0; i < n; ++i)
//        {
//            printf("%d:%d,%d,%d\n", i, sz[i], one[i], ans[i]);
//        }
    }
    return 0;
}

  

时间: 2024-11-05 12:08:50

ZOJ2834--Maximize Game Time(树形DP)的相关文章

HDU 1011 Starship Troopers(树形dp+背包)

Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13109    Accepted Submission(s): 3562 Problem Description You, the leader of Starship Troopers, are sent to destroy a base of

hdu4118 树形dp

http://acm.hdu.edu.cn/showproblem.php?pid=4118 Problem Description Nowadays, people have many ways to save money on accommodation when they are on vacation. One of these ways is exchanging houses with other people. Here is a group of N people who wan

hdu1561--H - ACboy needs your help(树形dp)

H - ACboy needs your help Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description ACboy has N courses this term, and he plans to spend at most M days on study.Of course,the profit he will gain from diffe

HDU 1011 Starship Troopers(树形DP)

Starship Troopers Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 62   Accepted Submission(s) : 12 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description You, the leader of

hdu1011 树形dp背包

http://acm.hdu.edu.cn/showproblem.php?pid=1011 Problem Description You, the leader of Starship Troopers, are sent to destroy a base of the bugs. The base is built underground. It is actually a huge cavern, which consists of many rooms connected with

洛谷 P2986 [USACO10MAR]Great Cow Gat…(树形dp+容斥原理)

P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat… 题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, of course, she would like to choose the most convenient location for the gathering to take place. Each cow lives in on

hdu-4118 Holiday&#39;s Accommodation(树形dp+树的重心)

题目链接: Holiday's Accommodation Time Limit: 8000/4000 MS (Java/Others)     Memory Limit: 200000/200000 K (Java/Others) Problem Description Nowadays, people have many ways to save money on accommodation when they are on vacation.One of these ways is exc

uva 10859 Placing Lampposts,树形dp

// uva 10859 Placing Lampposts // 树形dp // // 题目的意思是一个无向无环图中,有一些顶点和一些边 // 要在顶点上放置灯笼(灯笼可以照亮与它相邻接的点), // 使得所有的边都能被灯笼照亮,其中可能有一些边被两个灯笼 // 照亮,则要求使得所有边都被灯笼照亮所需灯笼的最小值, // 并且,此时边同时被两个灯笼照亮的数目应尽可能的多 // // 思路是 // d[i][0]表示在节点i不放置灯笼所需的灯笼的最小值 // d[i][1]表示在节点i放置灯笼所

hdu 4118 Holiday&#39;s Accommodation 树形dp

Holiday's Accommodation Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4118 Description Nowadays, people have many ways to save money on accommodation when they are on vacation.One of these ways is exchanging

sgu 143 Long live the Queen 简单树形dp

// sgu 143  Long live the Queen 简单树形dp // // 题意:在树上选一个连通字图,使得节点的权值之和最大 // f[i] 表示以该节点为根的字图权值之和的最大值 // 则有 f[i] = w[i] + sigma(max(0,f[j])) i是j的父节点 // 最后在所有的f中挑个最大值就是答案.... #include <algorithm> #include <bitset> #include <cassert> #include