• hdu 4276 The Ghost Blows Light 区域网络赛 1010 树上背包+spfa


    题目:
    给出一棵树,现要从树的1号节点走到n号节点,每条边都需要一定的时间才能走过,并且每个节点有相应的财宝,现在给出时间t,问能不能在时间t之内走到n节点且使得所获得的财宝最多(每个节点的财宝只能收集一次)

    分析:
    先spfa算出1号节点走到n号节点所经过的节点,算出的最短路若不满足小于等于给定的时间t,要被饿死。在spfa中,用path数组记录每个节点的前驱以及该节点是从那条边过来的,走完之后,用n的前驱把该路上的边权全部更新为0,表示不用时间花费,再在深搜之前把总时间减掉他即为其他走过了两次的不在最短路径上面的节点所花费的时间总和。
    树上背包的转移方程为
    dp[x][i] = ∑max(dp[x][j]+dp[y][i-j-temp])

    边为x与y,temp为当前的边权

    View Code
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 
      5 using namespace std;
      6 
      7 const int maxn = 205;
      8 const int maxm = 1005;
      9 const int inf = 1e9;
     10 #define debug puts("here");
     11 
     12 int dp[maxn][maxm],n,m;
     13 int po[maxm],tol;
     14 int w[maxn];
     15 bool use[maxm];
     16 int dis[maxm],q[maxm];
     17 
     18 struct node{
     19     int y,next,val;
     20 }edge[maxm];
     21 
     22 void add(int x,int y,int z){
     23     edge[++tol].y = y;
     24     edge[tol].val = z;
     25     edge[tol].next = po[x];
     26     po[x] = tol;
     27 }
     28 
     29 int spfa(){
     30     int h = 0,t = 0;
     31     q[t++] = 1;
     32     for(int i=1;i<=n;i++)
     33         dis[i] = inf;
     34     dis[1] = 0;
     35     int path[maxm] = {0};
     36     int qq[maxm];
     37     memset(use,false,sizeof(use));
     38     while(h<t){
     39         int x = q[h++];
     40         use[x] = false;
     41         for(int i=po[x];i;i=edge[i].next){
     42             int y = edge[i].y;
     43             if(dis[x]+edge[i].val<dis[y]){
     44                 dis[y] = dis[x]+edge[i].val;
     45                 path[y] = x;
     46                 qq[y] = i;
     47                 if(!use[y]){
     48                     q[t++] = y;
     49                     use[y] = true;
     50                 }
     51             }
     52         }
     53     }
     54     for(int i=n;i;i=path[i])
     55         edge[qq[i]].val = 0;
     56     return dis[n];
     57 }
     58 
     59 void dfs(int x){
     60     use[x] = true;
     61     for(int k=po[x];k;k=edge[k].next){
     62         int y = edge[k].y;
     63         if(use[y])
     64             continue;
     65         dfs(y);
     66         int temp = edge[k].val*2;
     67         for(int i=m;i>=temp;i--)
     68             for(int j=i-temp;j>=0;j--)
     69                 dp[x][i] = max(dp[x][i],dp[x][j]+dp[y][i-temp-j]);
     70     }
     71     for(int i=0;i<=m;i++)
     72         dp[x][i] += w[x];
     73 }
     74 
     75 int main(){
     76     freopen("sum.in","r",stdin);
     77     int x,y,z;
     78     while(cin>>n>>m){
     79         tol = 0;
     80         memset(po,0,sizeof(po));
     81         memset(dp,0,sizeof(dp));
     82         for(int i=1;i<n;i++){
     83             scanf("%d%d%d",&x,&y,&z);
     84             add(x,y,z);
     85             add(y,x,z);
     86         }
     87         for(int i=1;i<=n;i++)
     88             scanf("%d",&w[i]);
     89         int qq = spfa();
     90         if(qq>m){
     91             puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");
     92             continue;
     93         }
     94         memset(use,false,sizeof(use));
     95         m -= qq;
     96         dfs(1);
     97         cout<<dp[1][m]<<endl;
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    8天学会Hadoop基础(2)
    [Java]剑指offer:扑克牌顺子
    8天学会Hadoop基础(1):NameNode的工作机制
    [Java]剑指offer:构建乘积数组
    关于Hadoop启动之后jps没有namenode节点的解决方法
    剑指offer:对称的二叉树
    两只小熊队高级软件工程第七次作业敏捷冲刺5
    两只小熊队高级软件工程第七次作业敏捷冲刺4
    两只小熊队高级软件工程第七次作业敏捷冲刺3
    两只小熊队高级软件工程第七次作业敏捷冲刺2
  • 原文地址:https://www.cnblogs.com/yejinru/p/2677322.html
Copyright © 2020-2023  润新知