hihocoder1104(Dfs预处理+树形DP)

原创 2016年11月26日 11:07:49

题目描述

Little Hi is taking an adventure in Suzhou now. There are N beautiful villages in Suzhou which are numbered from 1 to N. They connected by N-1 roads in such a way that there is excactly one way to travel from one village to another. Little Hi gives each village a score according to its attractiveness. He is visiting village 1 now and plans to visit excatly M villages (including village 1) and maxize the total score of visited villages. Further more, K villages are recommended by Little Ho. He does not want to miss these recommended villages no matter what their attractiveness scores are.

Note that Little Hi visits every village on his travel route. Passing a village without visiting it is not allowed. Please find the maximum total score Little Hi can get.

算法思路

从题目中来看,我们发现这是一棵树,而且根据经过就必须观光的条件。我们可以进行第一次剪枝,剪枝过后所有的叶子结点都是重要的节点。很显然,这棵子树是我们必须遍历的。并且记录下在原树中与这棵子树直接相连的树的节点。
下一步,对所有记录下的节点进行树形DP,在遍历过剩下的这棵树之后就可以直接使用背包来进行扩展了,那么最后的最优解很显然我们也十分容易来构造。

ans=dp[mi]+sum(i)

其中i是第一次我们求得的子树的节点的数量,很显然,在这里问题是存在可能无解的,比如这棵子树的节点数量就超过了预期要游览的节点数量,那么就会无解,或者总的节点数量比想要游览的节点数量小,那么也是无解的(不过这里不可能)。否则必须存在解。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;

#define MAXN 105

int attr[MAXN],siz[MAXN];
vector<int>grid[MAXN];
vector<int>id;
bool isImportant[MAXN];
int n,k,m;
int dp[MAXN][MAXN];
int tongji[MAXN];

void Dfs1(int cur,int fa)
{//construct the subtree that we must visit
    int i,j;
    siz[cur] = 1;
//  printf("%d %d\n",cur,fa);

    for(i=0;i<grid[cur].size();i++){
        int dest = grid[cur][i];
        if(dest!=fa){
            Dfs1(dest,cur);
            isImportant[cur] |= isImportant[dest];
        }
    }

    if(isImportant[cur]){
        for(i=0;i<grid[cur].size();i++){
            int dest = grid[cur][i];
            if(dest!=fa){
                if(isImportant[dest]){
                    siz[cur] += siz[dest];
                    attr[cur] += attr[dest];
                }
                else
                    id.push_back(dest);
            }
        }
    }
    return;
}

void Dfs2(int cur,int fa)
{//construct the best answer via dynamic programming
    int i,j,k;
    siz[cur]=1;
    dp[cur][1] = attr[cur];

    for(i=0;i<grid[cur].size();i++){
        int dest = grid[cur][i];
        if(!isImportant[dest]&&dest!=fa){
            Dfs2(dest,cur);
            siz[cur] += siz[dest];
            for(j=siz[cur];j>1;j--){
                for(k=j-1;k>=0;k--){
                    dp[cur][j] = max(dp[cur][j],dp[cur][j-k]+dp[dest][k]);
                }
            }
        }
    }
    return;
}

int main()
{
    //freopen("input","r",stdin);
    int i,j,k;
    int tmp1,tmp2;

    memset(isImportant,false,sizeof(isImportant));
    memset(dp,0,sizeof(dp));
    memset(tongji,0,sizeof(tongji));

    scanf("%d%d%d",&n,&k,&m);

    for(i=1;i<=n;i++)
        scanf("%d",&attr[i]);

    for(i=0;i<k;i++){
        scanf("%d",&tmp1);
        isImportant[tmp1] = true;
    }

    for(i=0;i<n-1;i++){
        scanf("%d%d",&tmp1,&tmp2);
        grid[tmp1].push_back(tmp2);
        grid[tmp2].push_back(tmp1);
    }



    Dfs1(1,-1);

    if(n<m||siz[1]>m)
        printf("-1\n");
    else{
        m -= siz[1];
        for(i=0;i<id.size();i++){
            Dfs2(id[i],-1);
            for(j=m;j>=0;j--){
                for(k=j;k>=0;k--){
                    tongji[j] = max(tongji[j],tongji[k]+dp[id[i]][j-k]);
                }
            }
        }
        //printf("%d\n",attr[1]);
        printf("%d\n",attr[1]+tongji[m]);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

树形 DP 总结

一、介绍 1、什么是树型动态规划  顾名思义,树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有...
  • AngOn823
  • AngOn823
  • 2016年08月27日 14:12
  • 1628

树形DP—依赖背包模板

void DP(int x){ for(int i=0;i
  • xlzhang223
  • xlzhang223
  • 2016年03月12日 12:25
  • 235

树形DP总结,持续更新

树形DP总结,持续更新
  • Dacc123
  • Dacc123
  • 2016年01月03日 18:09
  • 403

树形动态规划(树状DP)小结

树状动态规划定义 之所以这样命名树规,是因为树形DP的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系。利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索...
  • txl16211
  • txl16211
  • 2015年04月29日 23:10
  • 9845

树形动态规划(树形DP)入门问题—初探 & 训练

树形DP入门 poj 2342 Anniversary party   先来个题入门一下~ 题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的...
  • txl16211
  • txl16211
  • 2015年04月29日 22:40
  • 9951

hdoj1561The more, The Better(树形dp,依赖背包)

题目:hdoj1561The more, The Better 题意:ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得...
  • y990041769
  • y990041769
  • 2014年07月23日 17:57
  • 3168

树形dp 小结

只能勉强称之为树形dp的傻逼问题:[POJ1655]Balancing Act 树的重心,经典问题,但是非常简单啊。。。 用size维护一下就好辣! [BZOJ2435][Noi2011]道路修...
  • Clove_unique
  • Clove_unique
  • 2016年11月17日 22:32
  • 558

leetcode -- 解题总结--DP与DFS, 递归

如果是求什么最小值或者判断是否存在,等求数字的题目,用dp如果是求所有possible solutions,用DFS backtracking...
  • xyqzki
  • xyqzki
  • 2015年12月16日 22:08
  • 823

树形dp学习

系统性的学习下树形dp。。虽然时间不太够了。。但是搏一搏,单车变摩托的道理还是要信的。。。。之前的太零散了,感觉很弱鸡。。。。 1.Hdu 2196 Computer  网上流传很广的一道求树的直径...
  • carryheart
  • carryheart
  • 2016年09月27日 20:48
  • 203

树形DP整理小结

树形DP: 在树上进行dp,树是递归的定义的,所以树形dp也是递归的求解,一般而言,dp[node]表示的是以node为根的子树能得到的最优解 一般而言,dp[node]需要从node的子结点进行状态...
  • tomorrowtodie
  • tomorrowtodie
  • 2016年08月24日 15:38
  • 981
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hihocoder1104(Dfs预处理+树形DP)
举报原因:
原因补充:

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