BZOJ 3743 Kamp(树形DP)

标签: dp
1人阅读 评论(0) 收藏 举报
分类:

题目链接:BZOJ 3743

题目大意:给出n个点n-1条边的一棵树,边有边权,有K个关键点,对于i=1~n,计算从第i个点起遍历K个关键点(不要求最后回到点i)经过的路径总长度的最小值。

题解:如果起点是K个关键点之一,答案会是2倍的K个关键点组成的虚树的边权和,再减去起点到剩下K-1个关键点的路径长度的最大值。如果起点不是K个关键点之一,答案会是起点到某个关键点的路经长度,加上以这个关键点为起点、遍历其余K-1个关键点的答案。
这个可以树形DP来求,详见代码及注释。

code(第一次写这种还要合并父节点信息的DP,感觉还是蛮巧妙的(*^▽^*))

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 500005
using namespace std;
typedef long long ll;
inline int read()
{
    char c=getchar(); int num=0,f=1;
    while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
    while (c<='9'&&c>='0') { num=num*10+c-'0'; c=getchar(); }
    return num*f;
}
struct edge{
    int to,ne,val;
}e[N<<1];
int n,m,tot,head[N],num[N],tag[N],t[N];
ll f[2][N],dis[N],ans[N];
inline void push(int x,int y,int w)
{
    e[++tot].to=y; e[tot].val=w; e[tot].ne=head[x]; head[x]=tot;
    e[++tot].to=x; e[tot].val=w; e[tot].ne=head[y]; head[y]=tot;
}
void dp(int now,int pre)
{
    num[now]=tag[now];  //num[now]表示以now为根的子树内的关键点数
    for (int i=head[now];i;i=e[i].ne)
    {
        int v=e[i].to; if (v==pre) continue;
        dp(v,now); if (!num[v]) continue;
        num[now]+=num[v]; dis[now]+=dis[v]+e[i].val;
        //dis[now]表示节点now到子树内所有关键点的路径长度的并
        int tmp=f[0][v]+e[i].val;
        if (tmp>f[0][now]) f[1][now]=f[0][now],f[0][now]=tmp;
         else if (tmp>f[1][now]) f[1][now]=tmp;
        //f[0/1][now]记录节点now向下走到子树内关键点的最大、次大路径长(来自不同子树)
    }
}
void pushdown(int now,int pre)  //整个子树的最优转移已经确定了,直接更新答案
{
    for (int i=head[now];i;i=e[i].ne)
    {
        int v=e[i].to; if (v==pre) continue;
        ans[v]=ans[now]+e[i].val;
        pushdown(v,now);
    }
}
void dfs(int now,int pre,ll up,ll sum) //up表示节点now向上走走到一个关键点的最大路径长
{
    ans[now]=2*sum-max(up,f[0][now]);
    for (int i=head[now];i;i=e[i].ne)
    {
        int v=e[i].to; if (v==pre) continue;
        if (num[v])
        {
            ll tmp=0;
            if (up||tag[now]) tmp=max(tmp,up+e[i].val);
            if (f[0][now]==f[0][v]+e[i].val) 
            {
                if (f[1][now]) tmp=max(tmp,f[1][now]+e[i].val);
            }
            else tmp=max(tmp,f[0][now]+e[i].val);
            dfs(v,now,tmp,sum);
        }
        else
        {
            ans[v]=ans[now]+e[i].val;
            pushdown(v,now);
        }
    }
} 
int main()
{
    n=read(); m=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read(),w=read();
        push(x,y,w);
    }
    for (int i=1;i<=m;i++)
    {
        t[i]=read();
        tag[t[i]]=1;
    }
    dp(t[1],0);
    dfs(t[1],0,0,dis[t[1]]);
    for (int i=1;i<=n;i++) printf("%lld\n",ans[i]);
    return 0;
}
查看评论

3743: [Coci2015]Kamp BFS

首先我们可以搞出这KK个点的一棵生成树,记这棵生成树的边权和为sumsum。 假设每次都要返回出发点xx,那么这里分两种情况讨论: 如果xx是KK个点中的某个点,那么答案为2×sum2\times...
  • Phenix_2015
  • Phenix_2015
  • 2016-05-21 22:52:19
  • 390

BZOJ 3743: [Coci2015]Kamp 树形dp

3743: [Coci2015]Kamp Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 540  Solved: 254 [Submit][S...
  • BlackJack_
  • BlackJack_
  • 2017-12-05 12:06:56
  • 62

【BZOJ4753】【JSOI2016】最佳团体(树形dp+二分)

DescriptionJSOI信息学代表队一共有N名候选人,这些候选人从1到N编号。方便起见,JYY的编号是0号。每个候选人都由一位编号比他小的候选人Ri推荐。如果Ri=0则说明这个候选人是JYY自己...
  • mousemjq
  • mousemjq
  • 2017-03-27 19:43:05
  • 581

3743: [Coci2015]Kamp

3743: [Coci2015]Kamp Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 442  Solved: 210 [Submit][S...
  • CRZbulabula
  • CRZbulabula
  • 2017-02-23 12:53:55
  • 288

bzoj 4472: [Jsoi2015]salesman 树形dp

题意某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇 之间都只有唯一的可能经过其它城镇的路线。 小T 可以准确地估计出在每个城镇停留的净收 益。这些净收益可能是负数,即...
  • qq_33229466
  • qq_33229466
  • 2017-04-18 15:47:28
  • 483

【bzoj2616】SPOJ PERIODNI 树形DP

DescriptionInput第1行包括两个正整数N,K,表示了棋盘的列数和放的车数。 第2行包含N个正整数,表示了棋盘每列的高度。Output包括一个非负整数,表示有多少种放置的方案,输出答案...
  • LOI_DQS
  • LOI_DQS
  • 2016-04-05 21:52:11
  • 811

[bzoj3743][Coci2015]Kamp

Description 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的。 有K个人(分布在K个不同的点)要集中到一个点举行聚会。 聚会结束后需要一辆车从举行聚会的这点出...
  • ScaPrt
  • ScaPrt
  • 2017-04-06 20:37:02
  • 257

树形DP例题整理

与普通dp类似,但是状态遍历不能简单的++i,而应该按由儿子到父亲的顺序完成。可以通过DFS递归完成,也可以按DFS(BFS)序从大到小完成,以保证先完成儿子再完成父亲。例题一 皇宫看守 tyvj_...
  • Mr_Poisonous
  • Mr_Poisonous
  • 2017-08-17 17:40:56
  • 141

BZOJ 3037 创世纪 树形DP

题目大意:给定一张有向图,每个点有且仅有一条出边,要求若一个点x扔下去,至少存在一个保留的点y,y的出边指向x,求最多扔下去多少个点 首先原题的意思就是支配关系 我们反向考虑 求最少保留的点 要求一...
  • PoPoQQQ
  • PoPoQQQ
  • 2014-10-10 17:17:47
  • 2143

BZOJ 2645 陶陶吃苹果 [树形DP]

题目传送门题解一道树形DP SB题,vijos入门经典题,noip普及组T1前道题。#include #include #include #include #include #define N 400...
  • lemonoil
  • lemonoil
  • 2017-07-17 11:53:55
  • 184
    个人资料
    持之以恒
    等级:
    访问量: 2639
    积分: 358
    排名: 22万+
    最新评论
    友情链接