CF77C Beavermuncher-0xFF(树形dp)

来源:互联网 发布:2016淘宝年会 马云 编辑:程序博客网 时间:2024/05/17 15:17

这题连写带改了将近一周。。。太弱了。。。很明显是个树形dp,然而细节有点多,蒟蒻认为不太好写。dp[i],表示在i的子树中,先花一个进入i,最后还要回到i,最多能吃多少只。考虑dp[x]如何求出,对于所有儿子y的dp[y],我们贪心的选取,即从大到小排序,先拿大的,再拿小的。要是还能接着拿,看儿子们还有多少剩余,能拿的就是儿子们的剩余与还能拿次数的最小值。注意还有一些回根x而拿掉的1.。。还要注意ll。代码写的丑成一坨,大家凑合看吧。。。

#include <bits/stdc++.h>using namespace std;#define ll long long#define N 100010#define inf 0x3f3f3f3finline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,a[N],rt=0,h[N],num=0,fa[N];//dp[i]--先花一个进入i,最后还要回到i,最多能吃多少只ll dp[N];struct edge{    int to,next;}data[N<<1];int dfs(int x){    dp[x]=1;ll res=0;//剩余    vector<ll>f;    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;if(y==fa[x]) continue;        fa[y]=x;res+=dfs(y);f.push_back(dp[y]);    }sort(f.begin(),f.end());    if(x==rt) a[x]++;//根不需要先花一个进入     if(f.size()>=a[x]-1){//不能全拿走         for(int i=1;i<=a[x]-1;++i) dp[x]+=f[f.size()-i]+1;return 0;    }for(int i=0;i<f.size();++i) dp[x]+=f[i]+1;a[x]-=f.size();//全拿走     if(a[x]-1>res) return dp[x]+=res*2,a[x]-1-res;//拿剩余     else return dp[x]+=(a[x]-1)*2,0;}int main(){//  freopen("a.in","r",stdin);    n=read();for(int i=1;i<=n;++i) a[i]=read();    for(int i=1;i<n;++i){        int x=read(),y=read();        data[++num].to=y;data[num].next=h[x];h[x]=num;        data[++num].to=x;data[num].next=h[y];h[y]=num;    }rt=read();dfs(rt);    printf("%I64d\n",dp[rt]-1);    return 0;}
原创粉丝点击