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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

hihocoder #1035 : 自驾旅行 III 树形DP

题目连接 思路参考 题目显然是一个树形DP,我们用dp[ i ][ j ]表示已经询问了子树i的所有关键节点,人车的一个状态。其中 j==0:人去,不管人是否回来 j==1:人去...

[hihocoder#1050 : 树中的最长路] 两种树形DP方法求树的最长路

[hihocoder#1050 : 树中的最长路] 两种树形DP方法求树的最长路 题目链接:[hihocoder#1050 : 树中的最长路] 解题思路:类似博文《 [POJ 2631/UVA 1...

hihocoder - 1479 树形dp

题意: 给出一个有根树,每个节点都有一个权值,在其中选出不是根节点的两个节点,将这两个节点与其父亲之间边删去,可以将这棵树分成三个部分,求一共有多少种分法,可以让这三个部分的权值和相等。 思路...
  • Bahuia
  • Bahuia
  • 2017年03月15日 15:23
  • 202

hihocoder-1055 刷油漆(树形DP)

第一次做树形DP,以前听过也找到过各种讲解,可是本身DP不太好,所以不敢接触... 实际做一次发现其实很好理解,只不过是将DP过程放在后序遍历中...

hihoCoder 1035 自驾旅行 树形DP

题目链接:http://hihocoder.com/problemset/problem/1035
  • ACMmaxx
  • ACMmaxx
  • 2014年07月21日 21:10
  • 2329

hihocoder 1243 树形DP

hihocoder1243 描述 王先生抢走了MX班里的妹子。为了报复,MX决定炸毁王先生的城市。 城市可以看成是一棵n个结点的无根树。MX需要炸毁树上的每一条边,但是同一条边仅能被...

[Offer收割]编程练习赛2 hihocoder 1272 买零食 (DFS 或 dp 水题)

[Offer收割]编程练习赛2 hihocoder 1272 买零食 (DFS 或 dp 水题)

hihoCoder [Offer收割]编程练习赛8【数论,dfs,dp,容斥】

题目:http://hihocoder.com/contest/offers8/problems【我只是简单地mark一下,看详细题解的请戳这里】A题肯定L和D的最大公因数肯定是循环节,然后直接暴力模...

Codeforces Round #135 (Div. 2) - D. Choosing Capital for Treeland(dfs / 树形DP)

题目: http://codeforces.com/problemset/problem/219/D 题意: 给出n个点,n-1条有向边的树,以一个点为中心,从这个点出发到其他各点需要更改的...

Codeforces 337 D Book of Evil(树形dp,两遍dfs)

题目链接: Codeforces 337 D Book of Evil 题意: 给一个nn个节点和n−1n-1条边的树,有mm个给定的点,求这nn个点中到这mm个点的距离都小于等于dd的点的个...
  • Ramay7
  • Ramay7
  • 2016年08月16日 11:52
  • 235
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hihocoder1104(Dfs预处理+树形DP)
举报原因:
原因补充:

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