• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dwtfukgv
博客园    首页    新随笔    联系   管理    订阅  订阅
HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)

题意:给定一棵树,每个点有个权值,每条边有权值,每经过边都会消耗相应的权值,但是点的权值只能获得一次,问你从 i 点出发能获得的最大权值是多少。

析:树形DP,就是太麻烦了,两次dfs,维护一共6个值分别是,从 i 出发的最大值并且返回 i, 从 i 出发的最大值并且不返回,从 i 出发的次大值并且不返回,从 i 出发的最大值的子树结点并且不返回,从 i 向父结点出发的最大值并且不返回,从 i 向父结点出发的最大值并且返回。

第一次dfs就能求出前四个,第二个dfs维护后面两个。

答案就是  max(所有子节点返回该节点+ 父亲节点不返回该节点, 有个子节点不返回该节点+从父亲节点返回该节点);

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e16;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
  return r >= 0 && r < n && c >= 0 && c < m;
}

int val[maxn];
struct Edge{
  int to, next, c;
};
Edge edge[maxn<<1];
int head[maxn], cnt;
int dp[maxn][4];
int ans[maxn];
/*
dp[i][0] the most val and back
dp[i][1] the most val and not back
dp[i][2] the second most val and not back
dp[i][3] the the son of the dp[i][1]
*/

void add_edge(int u, int v, int val){
  edge[cnt].to = v;
  edge[cnt].c = val;
  edge[cnt].next = head[u];
  head[u] = cnt++;
}

void dfs1(int u, int fa){
  dp[u][0] = dp[u][1] = val[u];
  dp[u][2] = 0;
  for(int i = head[u]; ~i; i = edge[i].next){
    int v = edge[i].to;
    if(v == fa)  continue;
    dfs1(v, u);
  }
  for(int i = head[u]; ~i; i = edge[i].next){
    int v = edge[i].to;
    if(v == fa)  continue;
    int c = edge[i].c;
    dp[u][0] += max(0, dp[v][0] - 2*c);
  }
  for(int i = head[u]; ~i; i = edge[i].next){
    int v = edge[i].to;
    if(v == fa)  continue;
    int c = edge[i].c;
    int val = dp[u][0] - max(0, dp[v][0] - 2*c) + max(0, dp[v][1] - c);
    if(val > dp[u][1]){
      dp[u][2] = dp[u][1];
      dp[u][1] = val;
      dp[u][3] = v;
    }
    else if(val > dp[u][2])
      dp[u][2] = val;
  }
}

void dfs2(int u, int fa, int fb, int fnb){
  ans[u] = max(fb+dp[u][1], fnb+dp[u][0]);
  for(int i = head[u]; ~i; i = edge[i].next){
    int v = edge[i].to;
    if(v == fa)  continue;
    int c = edge[i].c;
    int newfb = fb + dp[u][0] - max(0, dp[v][0] - 2*c);
    int newfnb;
    if(v == dp[u][3])
      newfnb = max(fb + dp[u][2] - max(0, dp[v][0]-2*c), fnb + dp[u][0] - max(0, dp[v][0]-2*c));
    else
      newfnb = max(fb + dp[u][1] - max(0, dp[v][0]-2*c), fnb + dp[u][0] - max(0, dp[v][0]-2*c));
    dfs2(v, u, max(0, newfb-2*c), max(0, newfnb-c));
  }
}

int main(){
  int T;  cin >> T;
  for(int kase = 1; kase <= T; ++kase){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)  scanf("%d", val+i);
    memset(head, -1, sizeof head);
    cnt = 0;
    for(int i = 1; i < n; ++i){
      int u, v, c;
      scanf("%d %d %d", &u, &v, &c);
      add_edge(u, v, c);
      add_edge(v, u, c);
    }
    dfs1(1, -1);
    dfs2(1, -1, 0, 0);
    printf("Case #%d:\n", kase);
    for(int i = 1; i <= n; ++i)
      printf("%d\n", ans[i]);
  }
  return 0;
}

  

 

posted on 2017-08-12 13:35  dwtfukgv  阅读(394)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3