hihocoder1104(Dfs预处理+树形DP)

来源:互联网 发布:中原农险数据脱敏 编辑:程序博客网 时间:2024/06/14 20:20

题目描述

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 105int 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;}
0 0
原创粉丝点击