【树形动规】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 ...
随机推荐
- PHP编译安装出错configure: error: mcrypt.h not found. Please reinstall libmcrypt的解决办法
1.下载libmcrypt wget http://jaist.dl.sourceforge.net/project/mcrypt/Libmcrypt/2.5.8/libmcrypt-2.5.8.ta ...
- MySQL日志概述
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3859866.html ...
- [Redis] windows下安装 Redis
一:Redis是什么? Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 通过https://github.c ...
- ASP.NET JSON的序列化和反序列化 之 Newtonsoft.Json
我们用到的类库为:Newtonsoft.Json,通过VS工具中NuGet程序包可以下载. 一:对象转json-序列化 public class Student { public int ID { g ...
- 玩javaweb的web.xml编译路径
有时候能够碰到这样的情况 缓存就是 清不掉 那就可以去寻找编译路径了 <Context docBase="E:\java-workspace\eigyo_com405" pa ...
- CSS3 颜色值HSL表示方式&简单实例
HSL色彩模式:就是色调(Hue).饱和度(Saturation).亮度(Lightness)三个颜色通道的改变以及它们相互之间的叠加来获得各种颜色,色调(Hue)色调最大值360,饱和度和亮度有百分 ...
- 在vSphere5.0虚拟机里的Ubuntu Server 32位安装JDK
本机操作系统Win7 服务器用vSphere 5.0 虚拟机 在虚拟机安装了Ubuntu Server 12.04 1.首先到Oracle官网上下载jdk-7u51-linux-i586.tar.g ...
- 如何在安卓/data(而不是/data/data)目录下进行文件的读写操作
分析:Android默认是无法直接操作/data目录的,只能读写程序自己的私有目录,也就是/data/data/package name/下,默认只能操作这个目录下的文件,也就是我们想直接读写/dat ...
- 一些硬件厂商的MAC号
http://standards.ieee.org/develop/regauth/oui/oui.txt https://svn.nmap.org/nmap/nmap-mac-prefixes
- ReactiveCocoa入门教程——第一部分
ReactiveCocoa iOS 翻译 2015-01-22 02:33:37 11471 6 15 本文翻译自RayWenderlich ReactiveCocoa ...