Codeforces Beta Round #69 (Div. 2 Only) E题


题意:给定一棵树,每个节点都有一个权值,给定出发点a,从a开始,到达每个点每个点就获得该点的一个权值(该节点相应减少一个),问最多可以得到多少值。。。

分析: dfs,将根节点的值增加1,然后对每颗子树的操作都一样,每次选择子树可能获得更多的优先选择,最后父节点和子节点可能还有剩余,还可以来回走动。。。
无语说是树形dp。。额。。。

代码:写得好戳啊。。。因为少了几个int64,wa了一大片。。。

#include <iostream>
#include<stdio.h>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

const int N=100010;
struct node
{
    int p;
    __int64 a, num; //num子树的最大可能
}tmp;
int n, flag[N];
__int64 a[N], ans;
vector<node> b[N];

int cmp(const node &a, const node &b)
{
    return a.num > b.num;
}

__int64 dfs(int p)
{
    vector<node>::iterator it;
    int cnt=0;
    for(it=b[p].begin(); it!=b[p].end(); it++)
    {
        if(flag[(*it).p]==0)
        {
            flag[(*it).p] = 1;
            (*it).num = dfs((*it).p);
            flag[(*it).p] = 0;
            (*it).a = a[(*it).p];
            cnt++;
        }
    }
    if(cnt==0)
    {
        return 0;
    }
    sort(b[p].begin(), b[p].end(), cmp);

    __int64 num=0;
    a[p]--;
    for(it=b[p].begin(); a[p]>0&&it!=b[p].end()&&(*it).num>0; it++)
    {
        if(flag[(*it).p]==0) //(*it).a始终是>=1的。。
        {
            (*it).a--;
            a[p]--;
            num += (*it).num+2;
        }
    }
    __int64 num1 = 0;
    for(it=b[p].begin(); it!=b[p].end(); it++)
    {
        if(flag[(*it).p]==0 && (*it).a>0)
        {
            num1 += (*it).a;
        }
    }
    num += min((__int64)a[p], num1)*2; //这两句
    a[p] -= min((__int64)a[p], num1);  //弄反了。。。
    a[p]++;
    return num;
}

int main()
{
    int i, j, k, head;
    while(scanf("%d", &n)!=EOF)
    {
        for(i=1; i<=n; i++)
        {
            scanf("%I64d", &a[i]);
            flag[i] = 0;
        }

        for(i=1; i<=n-1; i++)
        {
            scanf("%d %d", &j, &k);
            tmp.p = k;
            tmp.a = a[k];
            tmp.num = 0;
            b[j].push_back(tmp);
            tmp.p = j;
            tmp.a = a[j];
            tmp.num = 0;
            b[k].push_back(tmp);
        }
        scanf("%d", &head);
        a[head]++;

        flag[head] = 1;
        ans = dfs(head);
        printf("%I64d\n", ans);
        for(i=1; i<=n; i++)
        {
            while(!b[i].empty())
            {
                b[i].pop_back();
            }
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/ggggiqnypgjg/article/details/6912030