UVALive 4015 树形dp

 题目大意:

从一个根节点出发,走最多 x 的长度,问最多能走过多少个节点,图保证是一棵树

 

dp[0][i][j] , 表示走从i点为根的子树走过了j个点最后回到 i 最少需要多少时间
dp[1][i][j] , 同理,但表示不需要回到 i
那么由儿子不断向父亲更新,有4种情况

1.if(dp[0][u][k+j]<0 || dp[0][u][k+j]>dp[0][v][j]+dp[0][u][k]+2*e[i].d)
                    dp[0][u][k+j]=dp[0][v][j]+dp[0][u][k]+2*e[i].d;

2.if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[0][v][j]+dp[0][u][k]+e[i].d)
                    dp[1][u][k+j]=dp[0][v][j]+dp[0][u][k]+e[i].d;

3.if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[1][v][j]+dp[0][u][k]+e[i].d)
                    dp[1][u][k+j]=dp[1][v][j]+dp[0][u][k]+e[i].d;

4.if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[0][v][j]+dp[1][u][k]+2*e[i].d)
                    dp[1][u][k+j]=dp[0][v][j]+dp[1][u][k]+2*e[i].d;

 

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <iostream>

  4 #include <algorithm>

  5 #include <cmath>

  6 

  7 using namespace std;

  8 #define N 505

  9 #define ll long long

 10 ll dp[2][N][N];

 11 int fa[N] , n , m;

 12 int first[N],k;

 13 

 14 struct Edge{

 15     int y , next , d;

 16     Edge(int y=0 , int next=0 , int d=0):y(y),next(next),d(d){}

 17 }e[N<<1];

 18 

 19 void add_edge(int x , int y , int d)

 20 {

 21     e[k] = Edge(y , first[x] , d);

 22     first[x] = k++;

 23 }

 24 

 25 void dfs(int u)

 26 {

 27     dp[0][u][1] = 0;

 28     for(int i=first[u] ; ~i ; i=e[i].next){

 29         int v = e[i].y;

 30         dfs(v);

 31         for(int k=n ; k>=1 ; k--)

 32         {

 33             if(dp[0][u][k]<0) continue;

 34             for(int j=1 ; j<n ; j++){

 35                 if(dp[0][v][j]<0) continue;

 36                 if(dp[0][u][k+j]<0 || dp[0][u][k+j]>dp[0][v][j]+dp[0][u][k]+2*e[i].d)

 37                     dp[0][u][k+j]=dp[0][v][j]+dp[0][u][k]+2*e[i].d;

 38                 if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[0][v][j]+dp[0][u][k]+e[i].d)

 39                     dp[1][u][k+j]=dp[0][v][j]+dp[0][u][k]+e[i].d;

 40 

 41                 if(dp[1][v][j]<0) continue;

 42                 if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[1][v][j]+dp[0][u][k]+e[i].d)

 43                     dp[1][u][k+j]=dp[1][v][j]+dp[0][u][k]+e[i].d;

 44             }

 45             if(dp[1][u][k]<0) continue;

 46             for(int j=1 ; j<=n ; j++){

 47                 if(dp[0][v][j]<0) continue;

 48                 if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[0][v][j]+dp[1][u][k]+2*e[i].d)

 49                     dp[1][u][k+j]=dp[0][v][j]+dp[1][u][k]+2*e[i].d;

 50             }

 51         }

 52     }

 53 }

 54 

 55 int main()

 56 {

 57     #ifndef ONLINE_JUDGE

 58         freopen("a.in" , "r" , stdin);

 59     #endif // ONLINE_JUDGE

 60     int cas = 0;

 61     while(scanf("%d" , &n) , n)

 62     {

 63         printf("Case %d:\n" , ++cas);

 64         memset(first , -1 , sizeof(first));

 65         k = 0;

 66         for(int i=1 ; i<=n ; i++) fa[i]=i;

 67         for(int i=1 ; i<n ; i++){

 68             int u,v,d;

 69             scanf("%d%d%d" , &u , &v , &d);

 70             u++ , v++;

 71             add_edge(v , u , d);

 72             fa[u] = v;

 73         }

 74         int st;

 75         for(int i=1 ; i<=n ; i++)

 76             if(fa[i]==i) st = i;

 77 

 78         memset(dp , -1 , sizeof(dp));

 79         dfs(st);

 80         /*debug

 81         for(int i=1 ; i<=n ; i++){

 82             for(int j=1 ; j<=n ; j++){

 83                 printf("%4I64d" , dp[1][i][j]);

 84             }

 85             cout<<endl;

 86         }*/

 87         scanf("%d" , &m);

 88         for(int i=0 ; i<m ; i++){

 89             int x;

 90             scanf("%d" , &x);

 91             int ret = 0;

 92             for(int t=1 ; t<=n ; t++){

 93               //  cout<<dp[0][1][t]<<" "<<dp[1][1][t]<<endl;

 94                 if((dp[0][st][t]<=x && dp[0][st][t]>=0) || (dp[1][st][t]<=x && dp[1][st][t]>=0))

 95                     ret = max(ret , t);

 96             }

 97             printf("%d\n" , ret);

 98         }

 99     }

100     return 0;

101 }

 

你可能感兴趣的:(live)