刷题总结——鸭舌(ssoi)

题目:

题目背景

CF 77C

题目描述

小美喜欢吃鸭舌。
有一个 n 个点的树,每个节点 i ,第 i 个点上有 ai 个鸭舌。
小美一开始处于 x 号点。
每次小美可以选择一个与现在的点有边的点而且那个点还有鸭舌,那么小美会走到那个点并吃一个鸭舌。
要保证小美最后还是走到 x 号点。
问小美最多能吃几个鸭舌?

输入格式

输入第一行一个整数 n 。
接下来一行 n 个整数表示 ai 。
下面是 n-1 行每行两个整数表示一条边。
最后一行一个整数表示 x 。

输出格式

输出一行,一个整数,表示吃最多的鸭舌个数。

样例数据 1

输入  [复制]

 

1 3 1 3 2 
2 5 
3 4 
4 5 
1 5 
4

输出

6

样例数据 2

输入  [复制]

 

2 1 1 
3 2 
1 2 
3

输出

2

备注

【数据规模】
对于 30% 的数据:n≤5;ai≤5;
对于 100% 的数据:1≤n≤100000;0≤ai≤109;1≤x≤n。

题解:

  树形dp,优先考虑走完一个子树,然后如果有剩余就和子节点来回走;另外我tm刚开始把储存dp【son】的队列弄成全局变量了啊···草,还是用vector好

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int N=100005;
long long a[N];
long long  n,x;
long long  first[N],next[N*2],go[N*2],tot=0;
long long dp[N];
inline bool comp(long long a,long long b)
{
  return a>b;
}
inline void comb(long long a,long long b)
{
  next[++tot]=first[a],first[a]=tot,go[tot]=b;
  next[++tot]=first[b],first[b]=tot,go[tot]=a;
}
inline void dfs(long long now,long long fa)
{
  vector<long long>que;
  if(a[now]==0)  return;
  long long totl=0;
  for(long long e=first[now];e;e=next[e])
  {  
    if(go[e]==fa)  continue;
    dfs(go[e],now);
    que.push_back(dp[go[e]]);
    totl++;
  }
  sort(que.begin(),que.end(),comp);
  a[now]--;
  dp[now]=1;
  for(long long i=0;i<totl;i++)
  {
    long long temp=que[i];
    if (a[now]==0) break;
    if(temp!=0)
    {
      dp[now]+=temp+1;
      a[now]--;   
    }
    else break;
  }
  for(long long e=first[now];e;e=next[e])
  {
    if(go[e]==fa)  continue;
    long long temp=min(a[go[e]],a[now]);
    a[now]-=temp;
    dp[now]+=temp*2;
  }
}

int main()
{
  //freopen("tongue.in","r",stdin);
  //freopen("tongue.out","w",stdout);
  scanf("%I64d",&n);
  for(int i=1;i<=n;i++)
    scanf("%I64d",&a[i]);
  for(int i=1;i<n;i++)
  {
    long long a,b;
    scanf("%I64d%I64d",&a,&b);
    comb(a,b);
  }
  scanf("%I64d",&x);
  a[x]++;
  dfs(x,0);
  printf("%I64d",dp[x]-1);
  return 0;
}
原文地址:https://www.cnblogs.com/AseanA/p/7146344.html