您的位置:首页 > 其它

Codeforces Beta Round #69 (Div. 1 Only), problem: (C) Beavermuncher-0xFF 树形DP+优先队列

2013-02-25 13:33 501 查看
题意:让一个机器在一棵有根树上吃东西,这个机器每次只能移动到邻近的一个有动物的点,并且可以吃掉一只动物,然后进行新的运动。

问在机器可以返回根节点的情况下,机器最多可以吃的动物。

做法:唉,只能看看Tutorial
#1。运用贪心的策略,先求出每个子节点多可以吃到的动物数为y,自己节点剩下的动物数为x。一开始,父节点要去字节点,一定要消耗自己的一只动物,而这里就必须“择优录取子节点了”,即把子节点按x排序,然后进行一次遍历,如果最后父节点还可以剩下一些动物,那就在根据y进行计算,直到父子之间某一方的动物被吃光。

这里蕴含的贪心策略,一开始总是有点难不准。或许在有限的资源下,可以往资源利用率的方向思考,因为这里的资源利用率,是可以静态确定下来的,而不像背包问题。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#define LL long long
using namespace std;
const int LMT=100003;
LL have[LMT],get[LMT];
int next[LMT],all;
struct line
{
    int u,v,next;
}e[LMT<<1];
struct cmp
{
    bool operator()(const int a,const int b)
    {
        return get[a]<get[b];
    }
};
void dfs(int u,int pre)
{
    priority_queue<int,vector<int>,cmp>que;
    int tem;
    for(int x=next[u];x!=-1;x=e[x].next)
    if(e[x].v!=pre&&have[e[x].v])
    {
        have[e[x].v]--;
        dfs(e[x].v,u);
        que.push(e[x].v);
    }
    while(have[u]&&!que.empty())
    {
        get[u]+=get[que.top()]+2;
        have[u]--;
        que.pop();
    }
    for(int x=next[u];x!=-1&&have[u];x=e[x].next)
    if(e[x].v!=pre&&have[e[x].v])
    {
        tem=min(have[u],have[e[x].v]);
        get[u]+=tem<<1;
        have[u]-=tem;
    }
}
void insert(int u,int v)
{
    e[all].u=u;
    e[all].v=v;
    e[all].next=next[u];
    next[u]=all++;
}
int main()
{
    int n,s,u,v;
    memset(next,-1,sizeof(next));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%I64d",&have[i]);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        insert(u,v);
        insert(v,u);
    }
    scanf("%d",&s);
    dfs(s,0);
    printf("%I64d\n",get[s]);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: