HDU 5758 Explorer Bo (树形DP)

原创 2016年07月27日 14:46:54

题目:给你一棵树,用最少的链去覆盖这棵树,求链的最小总长度。

解析:num为叶子节点数,显然链数是(num+1)/2。如果是偶数,就是叶子节点到叶子节点,如果是奇数,那么就是在奇数-1情况下的树下加一条叶子到其祖先的链。

偶数的情况:从一个非叶子节点出发,如果其子节点的叶子节点是偶数,则ans+=2,如果是奇数,ans+=1。

奇数的情况:枚举一下那条单链所在的子树。

设dp[u][i][j] 在u的子树中,u的父边需要经过i次,j表示单链是否在该子树中。j=1就额外枚举单链所在子树即可,如果单链在该子树中,那么该树中的有效叶子节点-1(即奇数变偶数,偶数变奇数)。


[code]:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>

using namespace std;
const int maxn = 2e5+5;

struct Nod{
    int b,next;
    void init(int b,int next){
        this->b=b;this->next=next;
    }
}buf[2*maxn];
int n,E[maxn],len,cnt[maxn],ans,deg[maxn];
int dp[maxn][3][2];

void init(){
    ans = len = 0;
    memset(E,-1,sizeof(E));
    memset(dp,-1,sizeof(dp));
    memset(deg,0,sizeof(deg));
}
void add_edge(int a,int b){
    buf[len].init(b,E[a]);E[a]=len++;
    buf[len].init(a,E[b]);E[b]=len++;
    deg[a]++;deg[b]++;
}

void pre_dfs(int u,int pre){
    int i,v,f = 0;
    cnt[u] = 0;
    for(i = E[u];i != -1;i = buf[i].next){
        v = buf[i].b;
        if(v == pre) continue;
        pre_dfs(v,u);
        cnt[u]+=cnt[v];
        f = 1;
    }
    if(!f) cnt[u] = 1;
}
int dfs(int u,int pre,int s1,int s2){
    if(dp[u][s1][s2]!=-1) return dp[u][s1][s2];
    int i,v,ans = 0,num = -s1,tmp;
    for(i = E[u];i != -1;i = buf[i].next){
        v = buf[i].b;
        if(v == pre) continue;
        num += cnt[v];
        if(cnt[v]&1) ans += dfs(v,u,1,0)+1;
        else ans += dfs(v,u,2,0)+2;
    }
    if(s2){
        tmp = 0x3f3f3f3f;
        for(i = E[u];i != -1;i = buf[i].next){
            v = buf[i].b;
            if(v == pre) continue;
            if(cnt[v]&1){
                if(cnt[v]==1) tmp = min(tmp,ans);
                else tmp = min(tmp,ans+dfs(v,u,2,1)+2-(dfs(v,u,1,0)+1));
            }else tmp = min(tmp,ans+dfs(v,u,1,1)+1-(dfs(v,u,2,0)+2));
        }
        ans = tmp;
    }
    return dp[u][s1][s2] = ans;
}

int main(){
    int i,j,cas,u,v;
    scanf("%d",&cas);
    while(cas--){
        scanf("%d",&n);
        init();
        for(i = 1;i < n;i++){
            scanf("%d%d",&u,&v);
            add_edge(u,v);
        }
        if(n == 2){
            puts("1");
            continue;
        }
        int root=-1,num = 0;
        for(i = 1;i <= n;i++){
            if(deg[i]!=1&&root==-1){
                root = i;
            }
            num += deg[i]==1;
        }
        pre_dfs(root,-1);
        printf("%d\n",dfs(root,-1,0,num&1));
    }

    return 0;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 5758 Explorer Bo

DescriptionExplorer Bo likes exploring mazes around the world.Now he wants to explore a new maze. T...
  • bblss123
  • bblss123
  • 2016年07月26日 22:21
  • 359

hdu5758Explorer Bo

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5758 题意:给定一棵n个点的树,每次任选两个点,然后覆盖两点间的所有边,要求选择最少的次数覆盖所有的边,...
  • Fsss_7
  • Fsss_7
  • 2016年07月27日 21:24
  • 547

HDU 5760 Palindrome Bo(dp)

Description 给出n个数,要找到一个合法的最长子序列s,输出其长度,并且输出不同的s的个数。s序列必须是回文的,并且中间最小,往两边依次不减。s1与s2不同当且仅当长度不同或者存在某位s1...
  • V5ZSQ
  • V5ZSQ
  • 2016年08月08日 17:02
  • 309

[2016ACM多校] HDU5758 贪心 搜索

题意一棵树,要遍历所有的边,不能往回走。走到尽头的时候可以传送到另一个点,首先要保证使用传送次数最少。 思路所走的路径是最小链覆盖,由两个两个叶子的链组成,如果有奇数个子叶节点,那么会多一条从某一个叶...
  • SongBn
  • SongBn
  • 2016年07月27日 22:03
  • 277

hdu3534 树形dp(求树中两点之间的最大距离)

http://acm.hdu.edu.cn/showproblem.php?pid=3534 Problem Description In the Data structure...
  • u013573047
  • u013573047
  • 2015年02月14日 18:19
  • 1423

树的直径的两种求法(bfs与dp)

树的直径. 之前看树形dp的时候。对树的最远距离只是模糊理解了。并不是太懂。 然后发现了2196这个题。暴力tle一次后发现的树的直径转化问题。 然后网上介绍了4个题。 顺着做。 hdu-...
  • qq_27567837
  • qq_27567837
  • 2015年12月17日 01:20
  • 1618

BZOJ 2152 聪聪可可 树的点分治/树形DP

题目大意:给定一棵树,每条边上有边权,求距离为3的倍数的有序点对 树的点分治,对于每个重心统计出每棵子树距离重心长度为0/1/2的点的数量,计算出ans即可 最后ans*2+1 和n^2进行一下约...
  • PoPoQQQ
  • PoPoQQQ
  • 2014年10月27日 10:11
  • 2633

HDU 5758 Explorer Bo

DescriptionExplorer Bo likes exploring mazes around the world.Now he wants to explore a new maze. T...
  • bblss123
  • bblss123
  • 2016年07月26日 22:21
  • 359

2016多校联合第三场 HDU5758 Explorer Bo

题目大意: 给定一颗树,每次任意选取两个点,两点之间的所有边被标记,此次操作对答案的贡献为路径的长度;问在最少选取次数的情况下整个树被标记的最小答案。思路:对于第一个问题,最少选取次数显然是(叶子节点...
  • CQU_HYX
  • CQU_HYX
  • 2016年07月27日 12:54
  • 693

2016 暑假多校训练 第三场 1007 Explorer Bo HDU 5758

#pragma comment(linker,"/STACK:1024000000,1024000000") #include #include #include #include #incl...
  • tianji_fange_tuhao
  • tianji_fange_tuhao
  • 2016年07月27日 15:46
  • 225
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 5758 Explorer Bo (树形DP)
举报原因:
原因补充:

(最多只允许输入30个字)