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 ...
随机推荐
- map用法小例子
一. Map< Key , Value > m_Eg; 一般赋值表示成: TypeElem value; m_Eg[key] = value; 或 m_Eg.insert(make_ ...
- C#中的程序集和命名空间
C#中的程序集和命名空间 如果说命名空间是类库的逻辑组织形式,那么程序集就是类库的物理组织形式.只有同时指定类型所在的命名空间及实现该类型的程序集,才能完全限定该类型.<精通.NET核心技术-- ...
- 调用ffmpeg库编译时出现common.h:175:47: error: 'UINT64_C' was not declared in this scope
解决办法 出现错误:jni/ffmpeg/libavutil/common.h:175:47: error: 'UINT64_C' was not declared in this scope 解决: ...
- 关于解决用tutorial7教程中的代码打造一款自己的播放器中的声音噪音问题
////////////////////////////////////////////////////////////////////////////////////////////对于用FFMPE ...
- centos查看启动时间
系统启动时间 who -b date -d "$(awk -F. '{print $1}' /proc/uptime) second ago" +"%Y-%m-%d %H ...
- Z字形扫描矩阵
问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的4×4的矩阵, 1 5 3 9 3 7 5 ...
- jquery获取html元素的绝对位置和相对位置的方法
绝对位置坐标: 代码如下: $("#elem").offset().top$("#elem").offset().left 相对父元素的位置坐标: 代码如下: ...
- select2 选择框插件
<select id="selBusi_type"><select> //初始化业务类型下拉 var initBusiTypeSel = function( ...
- 世纪佳缘信息爬取存储到mysql,下载图片到本地,从数据库选取账号对其发送消息更新发信状态
利用这种方法,可以把所有会员信息存储下来,多线程发信息,10秒钟就可以对几百个会员完成发信了. 首先是筛选信息后爬取账号信息, #-*-coding:utf-8-*- import requests, ...
- mybatis由浅入深day02_9.3.5使用生成的代码_9.4逆向工程注意事项
9.3.5 使用生成的代码 需要将生成工程中所生成的代码拷贝到自己的工程中. 拷这4个到我们原来的spring_mybatis1216工程下 ItemsMapper.java package cn.i ...