hdu2196 Computer【树形DP】【换根法】
Computer
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 34390 Accepted Submission(s): 5383
Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
1 1
2 1
3 1
1 1
2
3
4
4
题意:
一棵有n个节点的树,有权边。问每个节点到其他节点的最远距离分别是多少。
思路:
如果固定一个节点,那么dfs找最远的距离就可以了。用dp[i]表示以i为根的子树中,i可到的最远距离。
对于任意一个节点i,他到达的最远节点有可能在子树中,也有可能不在子树中。所以我们分别找到子树中的最远距离和不在子树中的最远距离。
dfs1就是用dp存储了在子树中的最远距离。
dfs2就是把当前节点换到了根的位置,用f存储不在子树中的最远距离。那么他到他子树节点的距离是变短了的就不用管了。
把i换成根,把i的父亲father换下去,如果i在i的父亲这棵子树的最长路径上。father换下去之后,就要考虑原本以father为根的子树的第二长路径。
如果i不在father的最长路径上,那就是在f和dp中找大的加上当前路径长度。
//#include <bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<map>
#include<set> #define inf 0x3f3f3f3f
using namespace std;
typedef long long LL; const int maxn = ;
int head[maxn], dp[maxn], f[maxn], second[maxn], longest[maxn];
struct node{
int v;
int nxt;
int weight;
}edge[maxn * ];
int n, cnt; void addedge(int u, int v, int w)
{
edge[cnt].v = v;
edge[cnt].weight = w;
edge[cnt].nxt = head[u];
head[u] = cnt++;
edge[cnt].v = u;
edge[cnt].weight = w;
edge[cnt].nxt = head[v];
head[v] = cnt++;
} void dfs1(int rt, int fa)
{
for(int i = head[rt]; i != -; i = edge[i].nxt){
int son = edge[i].v;
if(son == fa)continue;
dfs1(son, rt);
//dp[rt] = max(dp[rt], dp[son] + edge[i].weight);
if(dp[son] + edge[i].weight > dp[rt]){
longest[rt] = son;
second[rt] = max(second[rt], dp[rt]);
dp[rt] = dp[son] + edge[i].weight;
}
else if(second[rt] < dp[son] + edge[i].weight){
second[rt] = dp[son] + edge[i].weight;
}
}
} void dfs2(int rt, int fa)
{
for(int i = head[rt]; i != -; i = edge[i].nxt){
int son = edge[i].v;
if(son == fa)continue;
if(longest[rt] == son)f[son] = max(f[rt], second[rt]) + edge[i].weight;
else f[son] = max(f[rt], dp[rt]) + edge[i].weight;
dfs2(son, rt);
}
} int main(){
while(scanf("%d", &n) != EOF){
cnt = ;
memset(head, -, sizeof(head));
for(int i = ; i <= n; i++){
int u, w;
scanf("%d%d", &u, &w);
addedge(u, i, w);
}
memset(dp, , sizeof(dp));
memset(second, , sizeof(second));
memset(longest, , sizeof(longest));
memset(f, , sizeof(f));
dfs1(, ); dfs2(, );
//f[1] = dp[1];
for(int i = ; i <= n; i++){
printf("%d\n", max(dp[i], f[i]));
}
}
return ;
}
hdu2196 Computer【树形DP】【换根法】的更多相关文章
- bzoj 3743 [Coci2015]Kamp——树形dp+换根
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...
- poj3585 Accumulation Degree[树形DP换根]
思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...
- 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686
换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...
- poj3585 Accumulation Degree(树形dp,换根)
题意: 给你一棵n个顶点的树,有n-1条边,每一条边有一个容量z,表示x点到y点最多能通过z容量的水. 你可以任意选择一个点,然后从这个点倒水,然后水会经过一些边流到叶节点从而流出.问你最多你能倒多少 ...
- [题解](树形dp/换根)小x游世界树
2. 小x游世界树 (yggdrasi.pas/c/cpp) [问题描述] 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当 ...
- HDU2196 - Computer(树形DP)
题目大意 给定一颗n个结点的树,编号为1~n,要求你求出每个结点能到达的最长路径 题解 用动态规划解决的~~~~把1 当成树根,这样就转换成有根树了.我们可以发现,对于每个结点的最长路,要么是从子树得 ...
- cf219d 基础换根法
/*树形dp换根法*/ #include<bits/stdc++.h> using namespace std; #define maxn 200005 ]; int root,n,s,t ...
- 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)
写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...
- poj 3585 Accumulation Degree(二次扫描和换根法)
Accumulation Degree 大致题意:有一棵流量树,它的每一条边都有一个正流量,树上所有度数为一的节点都是出口,相应的树上每一个节点都有一个权值,它表示从这个节点向其他出口可以输送的最大总 ...
- poj3585树最大流——换根法
题目:http://poj.org/problem?id=3585 二次扫描与换根法,一次dfs求出以某个节点为根的相关值,再dfs遍历一遍树,根据之前的值换根取最大值为答案. 代码如下: #incl ...
随机推荐
- Spring零散所得
Spring容器中bean的id或name,都可以有多个,且第一个为标识符(Qualifier),其余皆为别名(Alias).所以都可以通过applicationContext.getBean(&qu ...
- c/c++函数指针(3)
原文地址:http://blog.csdn.net/qingshuiyangfan/article/details/7692647 学习要点: 1,函数地址的一般定义和typedef简化定义; ...
- linux -- ubuntu 何为软件源
新手学Ubuntu的时候,一般不知道什么是源,但源又是Ubuntu下常用到的东西.因此,本文就详细介绍一下Ubuntu 源. 什么是软件源? 源,在Ubuntu下,它相当于软件库,需要什么软件,只要记 ...
- HBase源代码分析之MemStore的flush发起时机、推断条件等详情
前面的几篇文章.我们具体介绍了HBase中HRegion上MemStore的flsuh流程,以及HRegionServer上MemStore的flush处理流程.那么,flush究竟是在什么情况下触发 ...
- html5引擎开发 -- 引擎消息中心和有限状态机 - 初步整理 一
一 什么是有限状态机 FSM (finite-state machine),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型.他对于逻辑以及 ...
- float类型如何转换为string类型
在一些很大的float类型的地方会用科学记数法表示,这个时候如果想完整记录下来,还是得转字符串,这里书写一个float类型转string类型的方法 <?php function float_to ...
- swift--使用UserDefaults来进行本地数据存储
UserDefaults适合轻量级的本地客户端存储,存储一个值,新值可以覆盖旧值,可以重复存储,也可以存储一次,然后直接从UserDefaults里面读取上次存储的信息,很方便,用的时候,宏定义下,直 ...
- 【RF库Collections测试】Get Dictionary Items
Name:Get Dictionary ItemsSource:Collections <test library>Arguments:[ dictionary ]Returns item ...
- Nginx(三)-- 配置文件之日志管理
1.日志文件的默认存放位置 默认的日志文件存放位置在:nginx/logs/ 文件夹下,logs文件夹下有:access.log error.log nginx.pid 文件 2.nginx. ...
- C#中的抽象类与重写
今天的我们学习了好多,最初上午学习了文件流的方法,老师告诉我们是选修,可能以后不怎么用吧,但是还是想学下,似乎用个小程序读写文件很快地节奏,所以有点小兴趣学习,明天我再看看啦!今天之后学习了多态,继承 ...