5
19
2016
0

【合集】树形DP

POJ1947 Rebuilding Roads

状态转移方程实际上是一个泛化背包模型

注意"空间"的枚举顺序.

void DFS(int u)
{
    for(int i = 0; i <= m; i++) //初始化为无穷大
        dp[u][i] = INF;               
    dp[u][1] = 0;               //根结点本就一个点,不需要减边
    for(int i = head[u]; i != -1; i = e[i].next)
    {
        int v = e[i].to;    //u的子树
        DFS(v);
        for(int j = m; j >= 1; j--) 
        {
            for(int k = 0; k < j; k++)
            {
                if(k)   //不加子树k
                    dp[u][j] = min(dp[u][j], dp[u][j - k] + dp[v][k]);//此时dp[u][j-k]与dp[v][k]均被计算过 
                else    //加上子树k
                    dp[u][j] = dp[u][j] + 1;
            }
        }
    }
}
/*****main*****/
    DFS(root);
    int ans = dp[root][m];
    for(int i = 1; i <= n; i++)     //除了根节点,其他节点要想成为独立的根,必先与父节点断绝关系,所以要先加1
        ans = min(ans, dp[i][m] + 1);

POJ2486 Apple Tree

做了上面的题,这道题状态就很好想了.

可是:在进行背包的时候,对于某个孩子,走完之后是否回到根结点会对后面是否还能分配有影响

那就多加一维状态,分类讨论

void dfs(int s){
    int i;
    used[s]=true;
    for(i=0;i<=V;i++){
         dp[0][s][i]=dp[1][s][i]=val[s];//强制加入
    }
    for(i=0;i<g[s].size();i++){
        int t=g[s][i];
        if(used[t]) continue;
        dfs(t);
        for(int j=V;j>=0;j--){
            for(int k=0;k<=j;k++){//中间的桥梁一定要走,所以把状态依次转变过来
                Max(dp[0][s][j+2],dp[0][t][k]+dp[0][s][j-k]);
                Max(dp[1][s][j+2],dp[0][t][k]+dp[1][s][j-k]);
                Max(dp[1][s][j+1],dp[1][t][k]+dp[0][s][j-k]);
            }
        }
    }
}
/*****main*****/
    memset(dp,0,sizeof(dp));
    memset(used,false,sizeof(used));
    dfs(1);
    printf("%d\n",dp[1][1][V]);

POJ3140 Contestants Division

题意概括和建模很重要,还要有常~~识~~

树形Dp个毛线啊

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define LL __int64
struct node{
    int v , next ;
}edge[210000] ;
int head[110000] , cnt , vis[210000];
LL c[110000] , min1 , ans ;
void add(int u,int v) {
    edge[cnt].v = v ; edge[cnt].next = head[u] ;
    head[u] = cnt++ ;
    edge[cnt].v = u ; edge[cnt].next = head[v] ;
    head[v] = cnt++ ;
    return ;
}
LL f(LL a) {
    return a >= 0 ? a : -a ;
}
void dfs(int u) {
    int i ;
    LL temp ;
    for(i = head[u] ; i != -1 ; i = edge[i].next) {
        if( vis[i] == 0 ) {
            vis[i] = vis[i^1] = 1 ;
            dfs(edge[i].v) ;
            temp = f(ans-c[edge[i].v]-c[ edge[i].v ]) ;
            if( temp < min1 ) min1 = temp ;
            c[u] += c[ edge[i].v ] ;
        }
    }
}
int main() {
    int n , m , t = 0 , i , j , u , v ;
    while( scanf("%d %d", &n, &m) != EOF ) {
        if( n == 0 && m == 0 ) break ;
        memset(head,-1,sizeof(head)) ;
        memset(vis,0,sizeof(vis)) ;
        cnt = 0 ;
        ans = 0 ;
        for(i = 1 ; i <= n ; i++) {
            scanf("%I64d", &c[i]) ;
            ans += c[i] ;
        }
        min1 = ans ;
        while( m-- ) {
            scanf("%d %d", &u, &v) ;
            add(u,v) ;
        }
        dfs(1) ;
        printf("Case %d: %I64d\n", ++t, min1) ;
    }
    return 0 ;
}

POJ2057 The Lost House

(sang)(xin)(bing)(kuang)

 


LA2038 战略游戏

 

Category: 树套树 | Tags: 搜索 树形DP | Read Count: 396

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com