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为子树 ...
随机推荐
- 工作中常用的Linux命令:crontab命令,定时任务执行命令
本文链接:http://www.cnblogs.com/MartinChentf/p/6060252.html (转载请注明出处) crontab是一个用来设置.删除或显示供守护进程cron执行的定时 ...
- OpenCV笔记(1)(图片读取与现实、色彩空间、基础运算、均值方差、逻辑运算、泛洪填充、均值中值及自定义平滑)
一.图片读取和显示 import cv2 as cv # 图片读取cv.imread(img_path) car_img = cv.imread("car1.png") # 图片显 ...
- Centos 下硬盘分区的最佳方案
Centos7从零开始]Centos 下硬盘分区的最佳方案 2016年12月25日 10:09:02 浮華的滄桑 阅读数 41971 在对硬盘进行分区前,应该先弄清楚计算机担负的工作及硬盘的容量有 ...
- poj2386(dfs搜索水题)
Language:Default Lake Counting Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 42069 ...
- Hnoi2017试题泛做
Day1 4825: [Hnoi2017]单旋 注意到二叉查找树的一个性质:其中序遍历就是所有元素按权值排序的顺序. 所以我们可以离线地把这棵树的中序遍历求出来.然后我们在插入的时候就可以用一个set ...
- ServletConfig接口
ServletConfig接口 Servlet容器初始化Servlet对象时会为Servlet创建一个ServletConfig对象,在ServletConfig对象中包含了Servlet的初始化参数 ...
- 客户端框架-MVP
MVP Model-View-Presenter MVP是把MVC中的Controller换成了Presenter(呈现),目的就是为了完全切断View跟Model之间的联系,由Presenter充当 ...
- sqli-labs(45)
基于报错的password处的')闭合注入 就是没有报错信息 payload和43关一样的构造
- kali修改更新源及更新
进入源文件进行修改 leafpad /etc/apt/sources.list (其实系统本身就自带了更新源,去掉其注释也是可以的,现在官方源的下载速度也还ok,下面的三选一亦可) #kali官方源 ...
- RedisTemplate 用法
Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有 ...