Codeforces Round #384 (Div. 2)D. Chloe and pleasant prizes

题目链接:http://codeforces.com/contest/743/problem/D

好长时间没写树DP了,从打完比赛那天就一直想怎么写,感觉很生疏。写第二个DFS时卡了,请教了老房,学了一发他的UMAX,很巧妙。
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 2e5+5;
typedef long long ll;
ll arr[maxn];
ll sum[maxn];
ll son[maxn];
int vis[maxn];
vector<int> g[maxn];
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll dfs1(int u)
{
    int tt = g[u].size();
    int flag = 0;
    sum[u] += arr[u];
    for(int i=0;i<tt;i++)
    {
        int v = g[u][i];
        if(vis[v]) continue;
        vis[v] = 1;
        ll tmp = dfs1(v);
        sum[u] += tmp;
        flag = 1;
        son[u] = max(son[u],son[v]);
    }
    if(!flag) sum[u] = arr[u];
    son[u] = max(son[u],sum[u]);
    return sum[u];
}
ll ans = -inf;
void UMAX(ll& a,ll& b,ll c)
{
    if(c>a)
    {
        b = a;
        a = c;
    }
    else
    {
        if(c>b)
        {
            b = c;
        }
    }
}
void dfs2(int u)
{
    ll a = -inf;
    ll b = -inf;
    int tt = g[u].size();
    for(int i=0;i<tt;i++)
    {
        int v = g[u][i];
        if(vis[v]) continue;
        vis[v] = 1;
        dfs2(v);
        UMAX(a,b,son[v]);
    }
    if(b!=-inf) ans = max(ans,a+b);
}
int main()
{
    int n;cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%I64d",&arr[i]);
    }
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    memset(son,-inf,sizeof(son));
    memset(sum,0,sizeof(sum));
    memset(vis,0,sizeof(vis));
    vis[1] = 1;
    dfs1(1);
    memset(vis,0,sizeof(vis));
    vis[1] = 1;
    dfs2(1);
    if(ans==-inf)
    {
        printf("Impossible\n");
    }
    else
    {
        printf("%I64d\n",ans);
    }
    return 0;
}
卷珠帘

 

论姿势巧妙,还属陈老师
#include<cstdio>
#include<algorithm>
typedef long long ll;
const int N=200010;
const ll inf=1LL<<60;
int n,i,x,y,a[N],g[N],v[N<<1],nxt[N<<1],ed;ll f[N],dp[N],ans=-inf;
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x,int y){
  f[x]=a[x];
  dp[x]=-inf;
  for(int i=g[x];i;i=nxt[i]){
    int u=v[i];
    if(u==y)continue;
    dfs(u,x);
    f[x]+=f[u];
    if(dp[x]>-inf)ans=std::max(ans,dp[x]+dp[u]);
    dp[x]=std::max(dp[x],dp[u]);
  }
  dp[x]=std::max(dp[x],f[x]);
}
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++)scanf("%d",&a[i]);
  for(i=1;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
  dfs(1,0);
  if(ans>-inf)printf("%I64d",ans);else puts("Impossible");
}
Claris

转载于:https://www.cnblogs.com/littlepear/p/6200481.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值