zoukankan      html  css  js  c++  java
  • 树形dp

    HDU 1520 Anniversary party

    题意:有很多人之间有上下级关系,求没有直接上下级关系去参加party的最多人数。

    做法:dp[i][0]表示 结点 i 不参加,dp[i][1]表示 结点 i 参加。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<vector>
     7 #include<queue>
     8 
     9 using namespace std;
    10 
    11 #define inf 1e16
    12 #define eps 1e-6
    13 #define LL long long
    14 #define ULL unsigned long long
    15 #define MP make_pair
    16 #define pb push_back
    17 #define mod 1000000009
    18 #define lson l, m, rt<<1
    19 #define rson m+1, r, rt<<1|1
    20 #define mnx 20050
    21 
    22 int val[mnx], fst[mnx], nxt[mnx], fa[mnx], vv[mnx], e;
    23 int dp[mnx][2];
    24 void init(){
    25     memset( fa, -1, sizeof(fa) );
    26     memset( fst, -1, sizeof(fst) );
    27     memset( dp, 0, sizeof(dp) );
    28     e = 0;
    29 }
    30 void add( int u, int v ){
    31     vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
    32 }
    33 void dfs( int u ){
    34     dp[u][1] = val[u];
    35     for( int i = fst[u]; i != -1; i = nxt[i] ){
    36         int v = vv[i];
    37         dfs( v );
    38         dp[u][1] += dp[v][0];
    39         dp[u][0] += max( dp[v][1], dp[v][0] );
    40     }
    41 }
    42 int main(){
    43     int n;
    44     while( scanf( "%d", &n ) != EOF ){
    45         init();
    46         for( int i = 1; i <= n; ++i )
    47             scanf( "%d", &val[i] );
    48         int u, v;
    49         while( scanf( "%d%d", &u, &v ) != EOF ){
    50             if( u == 0 && v == 0 ) break;
    51             add( v, u );
    52             fa[u] = v;
    53         }
    54         int s;
    55         for( int i = 1; i <= n; ++i )
    56             if( fa[i] == -1 ){
    57                 s = i; break;
    58             }
    59         dfs( s );
    60         printf( "%d
    ", max( dp[s][0], dp[s][1] ) );
    61     }
    62     return 0;
    63 }
    View Code

    HDU 2196 Computer

    题意:求一个树上,每个结点 所能到达的最远距离是多少。

    做法:dp[i][0]表示结点 i 儿子当中的最远距离,dp[i][1]表示结点 i 儿子结点当中的次长距离,dp[i][2]表示结点 i 到 除了i结点和它儿子结点 的其他所有点的最远距离。两次dfs一下就好。还有一种做法是找树的直径,然后每个结点到树的直径两端点的距离的最大值就是答案。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #include<map>
     9 
    10 using namespace std;
    11 
    12 #define mnx 20050
    13 #define LL long long
    14 #define inf 0x3f3f3f3f
    15 #define MP make_pair
    16 #define lson l, m, rt << 1
    17 #define rson m+1, r, rt << 1 | 1
    18 #define mod 9973
    19 
    20 int fst[mnx], nxt[mnx], vv[mnx], cost[mnx], e;
    21 void init(){
    22     memset( fst, -1, sizeof(fst) );
    23     e = 0;
    24 }
    25 void add( int u, int v, int c ){
    26     vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
    27 }
    28 int dep[mnx], dp[mnx][3];
    29 bool cmp( int a, int b ){
    30     return a > b;
    31 }
    32 void update( int u, int val ){
    33     dp[u][2] = val;
    34     sort( dp[u], dp[u] + 3, cmp );
    35 }
    36 void dfs1( int u, int p ){
    37     for( int i = fst[u]; i != -1; i = nxt[i] ){
    38         int v = vv[i], c = cost[i];
    39         if( v == p ) continue;
    40         dfs1( v, u );
    41         update( u, dp[v][0] + c );
    42     }
    43 }
    44 void dfs2( int u, int p ){
    45     for( int i = fst[u]; i != -1; i = nxt[i] ){
    46         int v = vv[i], c = cost[i];
    47         if( v == p ) continue;
    48        // cout << dp[v][0] << " " << c << " " << dp[u][0] << endl;
    49         if( dp[v][0] + c == dp[u][0] )
    50             dp[v][2] = max( dp[v][2], max( dp[u][2] + c, dp[u][1] + c ) );
    51         else
    52             dp[v][2] = max( dp[v][2], max( dp[u][2] + c, dp[u][0] + c ) );
    53         dfs2( v, u );
    54     }
    55 }
    56 int n;
    57 void debug(){
    58     for( int i = 1; i <= n; ++i ){
    59         printf( "%d: %d
    ", i, dp[i][2] );
    60     }
    61 }
    62 int main(){
    63     while( scanf( "%d", &n ) != EOF ){
    64         init();
    65         for( int i = 2; i <= n; ++i ){
    66             int u, c;
    67             scanf( "%d%d", &u, &c );
    68             add( i, u, c ), add( u, i, c );
    69         }
    70         memset( dp, 0, sizeof(dp) );
    71         dfs1( 1, -1 );
    72         dfs2( 1, -1 );
    73        // debug();
    74         for( int i = 1; i <= n; ++i ){
    75             printf( "%d
    ", max( dp[i][0], dp[i][2] ) );
    76         }
    77     }
    78     return 0;
    79 }
    View Code

    POJ 2152 Fire

    题意:给一棵树,树有边权.现在要在一些点上建立消防站,每个点建站都有个w[i],如果不在当前的点上建站,也要依赖其他的消防站,并且距离不超过d[i]。求符合上述条件的最小费用建站方案。

    做法:dp[i][j]表示 i 结点所在的子树,必须在 j 结点建立消防站的花费。best[i]表示 i 结点所在的子树,满足条件时的最少花费。

    状态转移:dp[u][i] = w[i]; dp[u][i] += min( best[v], dp[v][i] - w[i] );

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #include<map>
     9 
    10 using namespace std;
    11 
    12 #define mnx 2050
    13 #define LL long long
    14 #define inf 0x3f3f3f3f
    15 #define MP make_pair
    16 #define lson l, m, rt << 1
    17 #define rson m+1, r, rt << 1 | 1
    18 #define mod 9973
    19 
    20 int fst[mnx], nxt[mnx], vv[mnx], cost[mnx], e;
    21 void init(){
    22     memset( fst, -1, sizeof(fst) );
    23     e = 0;
    24 }
    25 void add( int u, int v, int c ){
    26     vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
    27 }
    28 int d[mnx], dis[mnx], w[mnx], dp[mnx][mnx], best[mnx], n;
    29 void getdis( int dist, int u, int p ){
    30     dis[u] = dist;
    31     for( int i = fst[u]; i != -1; i = nxt[i] ){
    32         int v = vv[i], c = cost[i];
    33         if( v == p ) continue;
    34         getdis( dist + c, v, u );
    35     }
    36 }
    37 void dfs( int u, int p ){
    38     for( int i = fst[u]; i != -1; i = nxt[i] ){
    39         int v = vv[i];
    40         if( v == p ) continue;
    41         dfs( v, u );
    42     }
    43     getdis( 0, u, -1 );
    44     best[u] = inf;
    45     for( int i = 1; i <= n; ++i ){
    46         if( dis[i] > d[u] ) dp[u][i] = inf;
    47         else{
    48             dp[u][i] = w[i];
    49             for( int j = fst[u]; j != -1; j = nxt[j] ){
    50                 int v = vv[j];
    51                 if( v == p ) continue;
    52                 dp[u][i] += min( best[v], dp[v][i] - w[i] );
    53             }
    54         }
    55         best[u] = min( best[u], dp[u][i] );
    56     }
    57 }
    58 int main(){
    59    // freopen( "tt.txt", "r", stdin );
    60     int cas;
    61     scanf( "%d", &cas );
    62     while( cas-- ){
    63         init();
    64         scanf( "%d", &n );
    65         for( int i = 1; i <= n; ++i )
    66             scanf( "%d", &w[i] );
    67         for( int i = 1; i <= n; ++i )
    68             scanf( "%d", &d[i] );
    69         for( int i = 1; i < n; ++i ){
    70             int u, v, c;
    71             scanf( "%d%d%d", &u, &v, &c );
    72             add( u, v, c ), add( v, u, c );
    73         }
    74         dfs( 1, -1 );
    75         printf( "%d
    ", best[1] );
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    为服务部署 Jekins的使用
    spring cloud
    docker
    WebSocket
    idea
    maven
    SQL四种语言(DDL、 DML、 DCL、 TCL)
    十大经典排序
    AVL树的旋转图解和简单实现
    多个线程交替打印
  • 原文地址:https://www.cnblogs.com/LJ-blog/p/4419119.html
Copyright © 2011-2022 走看看