computer(树形dp || 树的直径)
Computer
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 38417 Accepted Submission(s): 6957
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
/*************************************************************************
> File Name: computer.cpp
> Author: CruelKing
> Mail: 2016586625@qq.com
> Created Time: 2019年09月23日 星期一 14时08分02秒
我的思路:先求出直径的两个端点,接着求出所有顶点到两个端点的距离,取其中最大的即是答案.
第二种思路:一个顶点距离其他顶点的最远距离要么经过儿子结点,要么经过父亲结点,那么我们就都求出来取其大就可以了.
需要注意的是,如果说一个说父亲的最远距离经过儿子的最远距离的话,儿子需要换一条路次短路.
************************************************************************/ #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
struct Edge {
int to, cost, next;
} edge[maxn << ]; int n, ans; int head[maxn], tot;
//int dp[maxn];//某棵树子树的大小 # TODO:这是用树的直径的时候保存的状态 int dp[maxn][];//用dp[i][0]表示i的子树的最远距离,dp[i][1]表示i的子树的次远距离
//dp[i][2]表示i的祖先的最远距离,所以答案取max(dp[i][0], dp[i][2]) void init() {
memset(head, -, sizeof head);
tot = ;
} void addedge(int u, int v, int w) {
edge[tot].to = v; edge[tot].next = head[u]; edge[tot].cost = w; head[u] = tot ++;
edge[tot].to = u; edge[tot].next = head[v]; edge[tot].cost = w; head[v] = tot ++;
} /*
void dfs(int u, int pre) {
//TODO:求解树的直径
//本题没用到该函数
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dfs(v, u);
if(ans < dp[u] + dp[v] + edge[i].cost) {
ans = dp[u] + dp[v] + edge[i].cost;
}
if(dp[v] + edge[i].cost > dp[u]) {
dp[u] = edge[i].cost + dp[v];
}
}
}
*/ /*
int d, M;
int A, B; int dist[maxn]; void dfs(int u, int pre, bool flag) {
//TODO:递归寻找树的直径的端点
if(d > M) {
M = d;
if(flag)
A = u;
else
B = u;
}
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(pre == v) continue;
d += edge[i].cost;
if(!flag) dist[v] = d;
dfs(v, u, flag);
d -= edge[i].cost;
}
} void dfs1(int u, int pre) {
//TODO;寻找每个点距离两个端点的最大值
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(pre == v) continue;
d += edge[i].cost;
dist[v] = max(d, dist[v]);
dfs1(v, u);
d -= edge[i].cost;
}
}
*/ void dfs(int u, int pre) {
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dfs(v, u);
int temp = ;
if(dp[u][] <= dp[v][] + edge[i].cost) {
dp[u][] = dp[u][];
dp[u][] = dp[v][] + edge[i].cost;
} else if(dp[u][] < dp[v][] + edge[i].cost) {
dp[u][] = edge[i].cost + dp[v][];
}
}
// printf("%d %d %d\n", u, dp[u][0], dp[u][1]);
} void dfs1(int u, int pre) {
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dp[v][] = max(dp[u][], dp[v][] + edge[i].cost == dp[u][] ? dp[u][] : dp[u][]) + edge[i].cost;
dfs1(v, u);
}
} int main() {
int v, w;
while(~scanf("%d", &n)) {
ans = ;
init();
memset(dp, , sizeof dp);
for(int i = ; i <= n; i ++) {
scanf("%d %d", &v, &w);
addedge(i, v, w);
}
/*TODO:利用树的直径求解本题
memset(dist, 0, sizeof dist);
d = M = 0;
dfs(1, -1, true);
M = 0;
dfs(A, -1, false);
// for(int i = 1; i <= n; i ++) {
// printf("%d\n", dist[i]);
// }
dfs1(B, -1);
for(int i = 1; i <= n; i ++) {
printf("%d\n", dist[i]);
}
*/
//TODO:利用树形dp求解本题
dfs(, -);
dfs1(, -);
for(int i = ; i <= n; i ++) {
printf("%d\n", max(dp[i][], dp[i][]));
}
}
return ;
}
computer(树形dp || 树的直径)的更多相关文章
- HDU 2196.Computer 树形dp 树的直径
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- hdu-2169 Computer(树形dp+树的直径)
题目链接: Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- Computer(HDU2196+树形dp+树的直径)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196 题目: 题意:有n台电脑,每台电脑连接其他电脑,第i行(包括第一行的n)连接u,长度为w,问你每 ...
- hdu 4607 树形dp 树的直径
题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n)个点,至少需要走多少距离(每条边的距离是1): 思路:树形dp求树的直径r: a:若k<=r+1 ...
- VIJOS1476旅游规划[树形DP 树的直径]
描述 W市的交通规划出现了重大问题,市政府下决心在全市的各大交通路口安排交通疏导员来疏导密集的车流.但由于人员不足,W市市长决定只在最需要安排人员的路口安放人员.具体说来,W市的交通网络十分简单,它包 ...
- POJ 3162.Walking Race 树形dp 树的直径
Walking Race Time Limit: 10000MS Memory Limit: 131072K Total Submissions: 4123 Accepted: 1029 Ca ...
- poj3162 树形dp|树的直径 + 双单调队列|线段树,好题啊
题解链接:https://blog.csdn.net/shiqi_614/article/details/8105149 用树形dp是超时的,, /* 先求出每个点可以跑的最长距离dp[i][0|1] ...
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
随机推荐
- Java三大体系JavaEE、JavaSE、JavaME的区别
Java由四方面组成: ●Java编程语言,即语法. ●Java文件格式,即各种文件夹.文件的后缀. ●Java虚拟机(JVM),即处理*.class文件的解释器. ●Java应用程序接口(Java ...
- Visual Studio 2008:路径设置
造冰箱的大熊猫,本文适用于Visual Studio 2008中文版@cnblogs 2018/11/30 1.头文件路径设置 如果头文件所在路径未在环境变量中定义,编译时会出现C1083错误,提示无 ...
- Nowcoder 练习赛 17 C 操作数 ( k次前缀和、矩阵快速幂打表找规律、组合数 )
题目链接 题意 : 给定长度为n的数组a,定义一次操作为: 1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007: 2. ...
- protoc 编译工具
在进行开发 protoc 之前,你需要首先在你的计算机中安装 protoc 编译工具. 下载编译工具 进入 Protocol Buffers 的源代码中然后选择发布的版本中,找到对应的版本.项目的链接 ...
- C++读入神器——文操快读(oj也可以用)
当某天,本蒟蒻沉迷于卡常的时候: 我-- 突然,YYKdalao说:用文操快读啊! 然后 喔-目瞪口呆 不多说,上源码: 本来用的读入方式: inline void Read( int &x ...
- oracle ROW_NUMBER() OVER(PARTITION BY '分组' ORDER BY '排序' DESC) 用法
转载:https://blog.csdn.net/dbagaoshou/article/details/51330829 SELECT * FROM ( SELECT ROW_NUMBER() OVE ...
- ...扩展运算符+rest参数+call/apply/bind
之前在set,map里面有提过扩展运算符的概念,但是今天偶然遇到一个问题,类似于扩展运算符的经典用法,突然发现对其了解不是很深,所以再来整理一下扩展运算符的相关知识. 重点:扩展运算符内部调用的是数据 ...
- linux 中的 "2>&1"含义
文章摘自:http://os.chinaunix.net/a2009/0903/996/000000996941.shtml 脚本是: nohup /mnt/Nand3/H2000G >/dev ...
- git梳理
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 本地库管理命令 git init ...
- echarts之bootstrap选项卡不能显示其他标签echarts图表
在echarts跟bootstrap选项卡整合的时候,默认第一个选中选项卡可以正常加载echarts图表,但是切换其他选项的时候不能渲染出其他选项卡echarts图表. 解决方法: 在js中添加代码: ...