【树形动规】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 ...
随机推荐
- 配置Nginx 1.8支持PHP 5.6
启动PHP和Nginx 修改Nginx配置文件/usr/local/nginx/conf/nginx.conf server { listen ; server_name localhost; loc ...
- 10.31 afternoon
巧克力棒(chocolate)Time Limit:1000ms Memory Limit:64MB题目描述LYK 找到了一根巧克力棒,但是这根巧克力棒太长了, LYK 无法一口吞进去.具体地,这根巧 ...
- 9.30 noip模拟试题
时限均为1s,内存 256MB 1.某种密码(password.*) 关于某种密码有如下描述:某种密码的原文A是由N个数字组成,而密文B是一个长度为N的01数串,原文和密文的关联在于一个钥匙码KEY. ...
- sql查看数据库表使用情况
如有更好的方式,希望交流. 感谢热心人,cc谢过 EXEC sys.sp_MSforeachtable @precommand = N'create table ##( 表名 sys ...
- Linux下inotify监控文件夹状态,发生变化后触发rsync同步
1.安装工具--inotifywget http://cloud.github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar ...
- 2014年10月16号--for语句实例
Console.WriteLine("一对小兔一个月之后长成大兔,再过一个月后生新的一对兔子,且两年之后有多少对兔子,就是三兔子幼兔,小兔,成兔"); Console.WriteL ...
- Asp.Net 注册 邮箱激活
数据库 表的设计 State为用户状态 0为禁用 1为可用 默认为0,下面有个UserGUID,这个字段将来用于激活账户 首先你要写一个表单,验证码神马的,这个我就不写了..直接写处理的 代码在 ...
- 九、C# 合式类型
本章要描述如何最终完善类型声明. 1.重写Ojbect中的成员 重写ToString() 默认情况下,在任何对象上调用 ToString()会返回类的完全限定名称,所以有时候需要重载这个函数, ...
- String、StringBuffer、StringBuilder
也说String. String:不可变字符序列. StringBuffer:线程安全的可变字符序列. StringBuilder:StringBuffer的非线程安全实现,JDK1.5+. publ ...
- Junit4_单元测试
不多说,直接练习学习. 1.将Junit4单元测试包引入项目:项目右键——“属性”,选择“Java Build Path”,然后到右上选择“Libraries”标签,之后在最右边点击“Add Libr ...