树型dp

来源:互联网 发布:魔兽世界nga数据库 编辑:程序博客网 时间:2024/05/08 03:08

树型动态规划

    树本身就是一个递归的结构,所以在树上进行动态规划或者递推是最合适不过的事情。
    必要条件:子树之间不可以相互干扰,如果本来是相互干扰的,那么我们必须添加变量使得他们不相互干扰。

列出一些经典问题吧:

1:给出一棵树 每个节点有权值  要求父节点和子节点不能同时取 求能够取得的最大值  (hdu1520)

2:给出一棵树,求离每个节点最远的点的距离 (hdu2196)

3:1>在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。求获得尽量多的宝物应该攻克哪M个城堡。 (hdu1561)

题解:树形dp+背包 

     2>每个节点有两个值bug和brain,当清扫该节点的所有bug时就得到brain值,只有当父节点被清空时,才可以清扫它的子节点,而清扫需要一定的人员。给定M个人员,N个结点的树,求最大brain和 (hdu1011)

     3>现在有n个村子,你想要用收买m个村子为你投票,其中收买第i个村子的代价是val[i]。但是有些村子存在从属关系,如果B从属于A国,则收买了A也意味着买通了B,而且这些关系是传递的。问你最小要付出的代价是多少? (poj3345)

4:1>一棵树,定义每个节点的balance值:去掉这点节点后的森林里所有树的最大节点数。求出最小的balance值和其所对应的节点编号(poj1655)

     2>给你一棵无向树 T,要求依次去除树中的某个结点,求去掉该结点后变成的森林 T' 中的最大分支。并要求该分支为去除的结点尽可能少。答案可能有多个,需要按照节点编号从小到大输出 (poj3107)

5:给一棵树, n结点<=1000, 和K <=200,  在这棵树上找大小为k的子树, 使其点权和值最大 (zoj3201)

6:给一个树状图,有n个点。求出,去掉哪个点,使得剩下的每个连通子图中点的数量不超过n/2。如果有很多这样的点,就按升序输出。n<=10000 (poj2378)

7:一棵n个结点的带权无根树,从中删去一条边,使得剩下来的两棵子树的节点权值之和的绝对值最小,并求出得到的最小绝对值 (poj3140)

8:给出一些点,有值,给出一些边,然后求去掉一条边后将分成连通的两部分,且两部分的差值最小 (hdu2242)

9:有n个点组成一个树,问至少要删除多少条边才能获得一棵有p个结点的子树 (poj1947)

10:一棵树n<=1000(节点的分支<=8),Snail在根处,它要找到在某个叶子处的house而其中一些节点上有worm,worm会告诉它的house是否在这个子树上求Snail最快寻找到house走过路径的期望值 (poj2057)

11:给你一颗苹果树,有N个节点每个节点上都有一个苹果也就是有一个权值,当你经过这个节点是你将得到这个权值,重复走节点是只能算一次,给你N-1条边。问你只能走K步能得到的最大权值和 (poj2486)

12:一颗二叉苹果树树上结苹果,要求剪掉几棵枝,然后求保留Q根树枝能保留的最多到苹果数 (ural1018)

13:给定一棵树,求最少连多少条边,使得每个点在且仅在某一个环内。 (poj1848)

14:在一棵树形的城市中建立一些消防站,但每个城市有一个最大距离限制,求需要的最小花费 (poj2152)

HDU 5723 Abandoned country (最小生成树+树形dp)

#include<bits/stdc++.h>using namespace std;#define N 1000000+10#define inf 0x3f3f3f3f#define ll long longstruct node1{    ll x,y,val;}f[N*10];struct node{    ll to,val;    node(){}    node(ll a,ll b){to=a;val=b;}};vector<node> mp[N];ll pre[N],sz[N],n,m;bool vis[N];ll finds(ll x){    return x==pre[x]?x:pre[x]=finds(pre[x]);}bool bing(ll x,ll y){    x=finds(x);    y=finds(y);    if(x!=y) {pre[x]=y;return 1;}    return 0;}bool cmp(node1 x,node1 y){    return x.val<y.val;}ll dfs(ll x){    vis[x]=sz[x]=1;    ll res=0;    for(ll i=0;i<mp[x].size();i++)    if(!vis[mp[x][i].to])    {        ll y=mp[x][i].to;        res+=dfs(y);        res+=sz[y]*(n-sz[y])*mp[x][i].val;        sz[x]+=sz[y];    }    return res;}void init(){    for(ll i=0;i<=n;i++) mp[i].clear(),pre[i]=i;    memset(vis,0,sizeof vis);    memset(sz,0,sizeof sz);}int main(){    ll t,tt=0;    scanf("%lld",&t);    while(t--)    {        scanf("%lld%lld",&n,&m);        init();        for(ll i=0;i<m;i++)            scanf("%lld%lld%lld",&f[i].x,&f[i].y,&f[i].val);        sort(f,f+m,cmp);        ll ans=0,x=n--;        for(ll i=0;i<m,n;i++)        if(bing(f[i].x,f[i].y))        {            ans+=f[i].val; n--;            mp[f[i].x].push_back(node(f[i].y,f[i].val));            mp[f[i].y].push_back(node(f[i].x,f[i].val));        }        n=x;        ll sum=dfs(1)*2;        printf("%lld %.2lf\n",ans,1.0*sum/(n-1)/n);    }}

http://poj.org/problem?id=2342

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>#include <vector>using namespace std;#define Del(a,b) memset(a,b,sizeof(a))const int N = 10000;int dp[N][3];  ///dp[i][0]表示当前i点不选 1表示选int father[N],vis[N];int n;void creat(int o){    vis[o]=1;    for(int i=1;i<=n;i++)    {        if(vis[i]==0 && father[i]==o)        {            creat(i);            dp[o][0]+=max(dp[i][0],dp[i][1]);            dp[o][1]+=dp[i][0];        }    }}int main(){    int i;    while(~scanf("%d",&n))    {        Del(dp,0);Del(father,0);        Del(vis,0);        for(i=1; i<=n; i++)        {            scanf("%d",&dp[i][1]);        }        int f,c,root;        root = 0;//记录父结点        bool beg = 1;        while (scanf("%d %d",&c,&f),c||f)        {            father[c] = f;            if( root == c || beg )            {                root = f;            }        }        while(father[root])//查找父结点            root=father[root];        creat(root);        int imax=max(dp[root][0],dp[root][1]);        printf("%d\n",imax);    }    return 0;}

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3201

经典例题讲解:

http://blog.163.com/dut_chiyang/blog/static/1976092042011920130333/

0 0
原创粉丝点击