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为子树 ...
随机推荐
- head first 设计模式笔记1-策略模式:模拟鸭子
1.第一个设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起.该原则几乎是所有设计模式背后的精神所在. 这个原则的另一种思考方式:把会变化的部分取出并封装起来,以 ...
- POJ 3422 矩阵取数 最小费用流拆点+负边
Kaka's Matrix Travels Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9153 Accepted: ...
- 【杂题】[LibreOJ #6608] 无意识的石子堆【容斥原理】【FFT】
Description Solution 943718401=225*2^22+1 显然每行必须有两个,我们不妨枚举有k列有2个石子,那么有2(n-k)列有1个石子. \[Ans=\sum\limit ...
- HGOI20190810 省常中互测3
Problem A 夏洛特 若当前处在点$(x,y)$下一时刻可以向该点四周任意方向走动一步, 初始在$(0,0)$是否存在一条合法的路线满足下列$n$个限制: 每一个限制形如$t_i , x_i ...
- 杜教筛&min_25筛复习
杜教筛 适用条件 你要能构造出\(g(x),h(x)\),使得\(h=f*g\). \(G(x),H(x)\)的值可以快速计算. 过程 我们要求的是\(F(n)=\sum_{i=1}^{n}f(i)\ ...
- 半径R覆盖最多点
struct point { double x, y; }; point p[N]; struct alpha { double v; bool flag; bool friend operator ...
- 高并发通信模型NIO
一.NIO和BIO的对比 BIO通信模型 2.配置 BIO tomcat server.xml NIO 3.NIO
- Mysql和Orcale的区别
有很多应用项目, 刚起步的时候用MYSQL数据库基本上能实现各种功能需求,随着应用用户的增多,数据量的增加,MYSQL渐渐地出现不堪重负的情况:连接很慢甚至宕机,于是就有把数据从MYSQL迁到ORAC ...
- Android动态广播的注册与销毁
一个内部类:BroadcastReceiver的子类,并定义收到广播之后的操作: class LockScreenBroadcastReceiver extends BroadcastReceiver ...
- 在electron中使用sqlite:sql.js简介
在electron中使用sqlite:sql.js简介 在开发electron应用的时候如果想要使用sqlite3,步骤上除了npm安装以外还要rebuild,比较麻烦.如果你想找一个开箱即用的sql ...