标签:int top dfs 算法 len 树上 最长 define
关于如何求得树中每个点最长路的O(n)算法:
1.算法流程:
- 求出树上的直径,在第二次dfs中求出从直径一端点到每个点的距离
再跑一次dfs,求出另一端点到每个点的距离,并更新每个点的最长路
2. 算法实现:
#include<bits/stdc++.h>
#define ll long long
#define N 10000005
#define f1(i,n,m) for(int i=n;i<=m;++i)
using namespace std;
template<typename T>
void read(T &x) {
int w = 1;
x = 0;
char c = getchar();
while (c < '0' || c > '9') {if (c == '-')w = -1;c = getchar();}
while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + c - '0';c = getchar();}
x *= w;
}
int tot, n, m, cnt, ans, root, mx;
int l1 = 0, l2 = 0, r1 = 1, r2 = 1, top = 1;
int head[N], to[N], nex[N], w[N];
int len[N], q1[N], q2[N], num[N];
void add(int x, int y, int wi) {
to[++tot] = y;
w[tot] = wi;
nex[tot] = head[x];
head[x] = tot;
}
void dfs(int x, int f, int dep) {
int y;
if (len[x] < dep)len[x] = dep;
if (dep >= mx)mx = dep, root = x;
for (int i = head[x]; i; i = nex[i]) {
y = to[i];
if (y == f)continue;
dfs(y, x, dep + w[i]);
}
}
void move(int top) {
if (top > n)return;
while (len[q1[r1]] < len[top] && l1 <= r1)r1--;
while (len[q2[r2]] > len[top] && l2 <= r2)r2--;
q1[++r1] = top, q2[++r2] = top;
}
signed main() {
int x, y;
read(n), read(m);
f1(i, 2, n) {
read(x), read(y);
add(i, x, y);
add(x, i, y);
}
dfs(1, 0, 0);
dfs(root, 0, 0);
dfs(root, 0, 0);
f1(i, 1, n) {
while (top <= n + 1 && len[q1[l1]] - len[q2[l2]] <= m)
ans = max(ans, top - i), move(top++);
if (l1 <= r1 && q1[l1] <= i)l1++;
if (l2 <= r2 && q2[l2] <= i)l2++;
}
printf("%d", ans);
}
3. 算法依据:
树上任意一点的最长路的一端必定在这棵树某个直径的一个端点
4. 算法证明:
标签:int,top,dfs,算法,len,树上,最长,define 来源: https://www.cnblogs.com/windf/p/16659748.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。