hihocoder1104(Dfs预处理+树形DP)

题目描述

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;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aaron_1996/article/details/53349400
文章标签: dfs
个人分类: 图算法 动态规划
想对作者说点什么? 我来说一句

华中科大2011状态压缩DP树形DP

2018年05月15日 905KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭