【树形动规】HDU 5834 Magic boy Bi Luo with his excited tree
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5834
题目大意:
一棵N个点的有根树,每个节点有价值ci,每条树边有费用di,节点的值只能取一次,边权每次经过都要扣,问从每一个节点开始走最大能获得的价值。
题目思路:
【树形动态规划】
首先用dfs求出从根1往下走的:节点u往下走最后回到节点u的最大值g[u],节点u往下走最后不回到u的最优值和次优值f[0][u],f[1][u]
接着考虑一个节点u,除了以上的情况还有可能是往它的父亲方向走,这里就分两种,一种是走父亲那边再回来走自己的子树,还有一种是走自己的子树再回来走父亲那边
(肯定最后都不会特意回到u,因为边权>0,回到自己不会更优)而这些状态都可以通过dfs里求得f和g推出。
具体推法我已写在代码注释中,希望没有写错。。
//
//by coolxxx
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<iomanip>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<bitset>
#include<memory.h>
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<stdbool.h>
#include<math.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define eps (1e-8)
#define J 10
#define mod 1000000007
#define MAX 0x7f7f7f7f
#define PI 3.14159265358979323
#define N 100004
using namespace std;
typedef long long LL;
int cas,cass;
int n,m,lll,ans;
int w[N],last[N],g[N];
int f[][N],from[][N],h[][N];
struct xxx
{
int next,to,d;
}a[N+N];
bool mark[N];
void add(int x,int y,int z)
{
a[++lll].d=z;
a[lll].to=y;
a[lll].next=last[x];
last[x]=lll;
}
void dfs(int u,int fa)//从根开始往下走的解
{
int i,j,v;
g[u]=w[u];
for(i=last[u];i;i=a[i].next)
{
v=a[i].to;
if(v==fa)continue;
dfs(v,u);
g[u]+=max(,g[v]-a[i].d-a[i].d);//g[u]统计最后回到u的最优解
}
for(i=last[u];i;i=a[i].next)
{
v=a[i].to;
if(v==fa || f[][v]<=a[i].d)continue;
j=g[u]-max(,g[v]-a[i].d-a[i].d)+max(,f[][v]-a[i].d);
//枚举从u哪一条走下去不回,如果g[u]计算时有走v则要扣掉,再加上选择走v不回的最优值
if(f[][u]<=j)//不回u的最优值
{
f[][u]=f[][u],from[][u]=from[][u];
f[][u]=j,from[][u]=i;
}
else if(f[][u]<j)//不回u的次优值
f[][u]=j,from[][u]=i;
}
f[][u]=max(f[][u],g[u]);
f[][u]=max(f[][u],g[u]);
}
void work(int u,int fa)//计算最后答案
{
int i,j,v;
for(i=last[u];i;i=a[i].next)
{
v=a[i].to;
if(v==fa)return;
j=max(,g[v]-a[i].d-a[i].d);//u走到v再走回来是否更优
h[][v]=f[][v]+max(,g[u]-j-a[i].d-a[i].d);//g[u]扣除掉走v子树的值,先从v向上走到u再从u走回来,然后走回v的最优值
h[][v]=f[][v]+max(,g[u]-j-a[i].d-a[i].d);//次优值
from[][v]=i;
if(g[v]>=a[i].d+a[i].d)//这种情况下前面多扣了一次边权
{
if(from[][u]!=i)h[][v]=h[][u]+a[i].d;//v往上走回头再往下走不回头
else h[][v]=h[][u]+a[i].d;//当前是最优值,选另一条走次优值
}
else//前面少扣了一次边权
{
if(from[][u]!=i)h[][v]=h[][u]+g[v]-a[i].d;//v往下走回头再往上走不回头
else h[][v]=h[][u]+g[v]-a[i].d;
}
if(h[][v]>h[][v])swap(h[][v],h[][v]),swap(from[][v],from[][v]);
if(h[][v]>h[][v])swap(h[][v],h[][v]),swap(from[][v],from[][v]);
g[v]+=max(,g[u]-j-a[i].d-a[i].d);//更新答案
work(v,u);
}
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("1.txt","r",stdin);
// freopen("2.txt","w",stdout);
#endif
int i,j,k;
int x,y,z;
// for(scanf("%d",&cass);cass;cass--)
for(scanf("%d",&cas),cass=;cass<=cas;cass++)
// while(~scanf("%s",s+1))
// while(~scanf("%d",&n))
{
mem(f,);mem(from,);mem(last,);lll=;
printf("Case #%d:\n",cass);
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&w[i]);
for(i=;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dfs(,);
h[][]=f[][],h[][]=f[][];
work(,);
for(i=;i<=n;i++)
printf("%d\n",h[][i]);
}
return ;
}
/*
// //
*/
【树形动规】HDU 5834 Magic boy Bi Luo with his excited tree的更多相关文章
- hdu 5834 Magic boy Bi Luo with his excited tree 树形dp+转移
Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 13107 ...
- HDU 5834 Magic boy Bi Luo with his excited tree(树形dp)
http://acm.hdu.edu.cn/showproblem.php?pid=5834 题意: 一棵树上每个节点有一个价值$Vi$,每个节点只能获得一次,每走一次一条边要花费$Ci$,问从各个节 ...
- 动态规划(树形DP):HDU 5834 Magic boy Bi Luo with his excited tree
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8UAAAJbCAIAAABCS6G8AAAgAElEQVR4nOy9fXQcxZ0uXH/hc8i5N+
- HDU 5834 Magic boy Bi Luo with his excited tree
树形dp. 先dfs一次处理子树上的最优解,记录一下回到这个点和不回到这个点的最优解. 然后从上到下可以推出所有答案.细节较多,很容易写错. #pragma comment(linker, " ...
- hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)
题目链接: Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others) Memory Limit: ...
- 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree
// 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以 ...
- 2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree
Magic boy Bi Luo with his excited tree Problem Description Bi Luo is a magic boy, he also has a migi ...
- HDU5834 Magic boy Bi Luo with his excited tree(树形DP)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5834 Description Bi Luo is a magic boy, he also ...
- hdu5834 Magic boy Bi Luo with his excited tree 【树形dp】
题目链接 hdu5834 题解 思路很粗犷,实现很难受 设\(f[i][0|1]\)表示向子树走回来或不回来的最大收益 设\(g[i][0|1]\)表示向父亲走走回来或不回来的最大收益 再设\(h[i ...
随机推荐
- asp.net 的脚本
asp.net的 Web 控件有时会包装一些用户端脚本 (client-side scripting),在控件被绘制时输出到用户端,这些脚本多数被包装在 DLL 的资源档中,并由 ScriptReso ...
- HTML5 <Audio/>标签Api整理(二)
1.实例2: 相对较完整 Html代码: <style> #volumeSlider .slider-selection { background:#bababa; } </styl ...
- php函数serialize()与unserialize()
serialize()和unserialize()在php手册上的解释是: serialize — Generates a storable representation of a value ser ...
- 灵活运用绑定变量---declare匿名块使用绑定变量
declare type cur01 is ref cursor; v_cur cur01; v_match123 varchar2(2000); v ...
- express 安装与卸载
卸载: npm uninstall -g express安装指定版本: npm install -g express@3.5.0查看版本: express -V注意express -V中的V要大写,不 ...
- Windows的命令行怎么支持通配符
摸索出一个小技巧,虽然Windows的命令行本身不支持通配符,但可以在脚本里把传进来的参数当通配符用 只要加上@ARGV = glob "@ARGV";就行了 @ARGV = gl ...
- gzip命令
http://www.cnblogs.com/peida/archive/2012/12/06/2804323.html 减 少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时, ...
- YZOI回忆录&&YZOI3.0介绍&&某些资源的分享
“那段时光就像块透明的琉璃,美得那么虚幻.飘渺.可是它毕竟在我生命里闪现,哪怕如萤光一样微弱,却照亮了我整个心房.”1.前序伴随着yzoi2.0版本离我而去的是我半年的OI生涯,在这半年内我步入了一个 ...
- 原型链和new
http://www.cnblogs.com/objectorl/archive/2010/01/11/Object-instancof-Function-clarification.html 构造器 ...
- CodeIgniter框架——介绍
CodeIgniter 是一个应用程序框架 CodeIgniter 是一个为用 PHP 编写网络应用程序的人员提供的工具包.它的目标是实现让你比从零开始编写代码更快速地开发项目,为此,CI 提供了一套 ...