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为子树 ...
随机推荐
- 学习springboot(三)——springboot+mybatis出现org.apache.ibatis.binding.BindingException: Invalid bound state
有段时间没搭建过了生疏了,记录下出现此情况且你能通过注解的方式正常进行数据库操作,只是通过mapper.xml不行就可以看看这个了.主要问题应该是配置上,不要太自信自己,再仔细找找.1.查看xml是否 ...
- prometheus 标签修改promSQL
relabel_configs 根据prometheus 监控k8s配置文件中学习 未修改前默认配置文件: 网页显示: 修改配置文件后: 网页显示: 服务发现网页: 总结: 在数据采集之前对任何目标的 ...
- python类装饰器即__call__方法
上一篇中我对学习过程中的装饰器进行了总结和整理,这一节简单整理下类装饰器 1.类中的__call__方法: 我们在定义好一个类后,实例化出一个对象,如果对这个对象以直接在后边加括号的方式进行调用,程序 ...
- jar 在windows 启动服务,卸载服务,停止端口
参考:https://www.cnblogs.com/zhuchunlei/p/9469569.html 1,启动服务 install.bat @echo off SET JAVA_HOME=&qu ...
- 使用oracle删除表中重复记录
(1)使用用rowid方法 查询重复数据:select * from person a where rowid !=(select max(rowid) from person b where a.c ...
- Zookeeper(六)服务器
Zookeeper(六)服务器 zkServer.cmd中声明 首先启动QuorumPeerMain set ZOOMAIN=org.apache.zookeeper.server.quorum.Qu ...
- 2018092609-2 选题 Scrum立会报告+燃尽图 03
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8680 一.小组情况组长:贺敬文组员:彭思雨 王志文 位军营 杨萍队名:胜 ...
- What exactly is the parameter e (event) and why pass it to JavaScript functions?
What exactly is the parameter e (event) and why pass it to JavaScript functions? 问题 Well, when I lea ...
- App架构设计:接口的设计
安全机制的设计 现在,大部分App的接口都采用RESTful架构,RESTFul最重要的一个设计原则就是,客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验 ...
- 深入理解android的UI更新机制
深入理解android的UI更新机制 由问题开始: 如何更新android UI? 可以通过如下方法: 在主线程里直接操作UI控件. handler.post(Runnable) runOnUiThr ...