题目大意:
给出
N
N
个点,条边的连通图.
现要求删除一条边,使得连通块的直径总和最大.所谓连通块的直径是指连通块中最远两点之间的距离。问直径总和最大是多少?
分析:
暴力就是每次拆掉一条边,然后暴力求解分成的
2
2
棵树的树上最长链的总和,不过我们发现,
可以预处理出每一棵子树的
①最大直径
②子树中的最远点,次远点,与次次远点与根的距离与所在的子树位置(任意个结点不能在同一颗子树)
③直径最大的两颗子树的直径跟所在位置
然后,每次拆掉一条边,以后,分成的子树的两个根,设为
x,y
x
,
y
,
那么它们相邻,我们设
y
y
为的儿子,
那么显然以
y
y
位根子树的直径是已知的,即
而对以
x
x
<script type="math/tex" id="MathJax-Element-557">x</script>为根子树,分类讨论一下即可
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 100005
using namespace std;
struct Node {
int To, w, nxt;
}e[2*N];
int f[N], g[N][3][2], c[N][2][2], Ls[N], n, ans, cnt = 0;
void Addedge(int u, int v, int w) {
e[++cnt].To = v, e[cnt].w = w, e[cnt].nxt = Ls[u], Ls[u] = cnt;
}
void dfs1(int x, int father) {
for (int k = Ls[x]; k ; k = e[k].nxt) {
if (e[k].To == father) continue;
int y = e[k].To;
dfs1(y, x);
if (f[y] > c[x][1][1]) {
memcpy(c[x][2], c[x][1], sizeof(c[x][1]));
c[x][1][1] = f[y];
c[x][1][2] = y;
} else if (f[y] > c[x][2][1]) c[x][2][1] = f[y], c[x][2][2] = y;
int z = g[y][1][1] + e[k].w;
if (z > g[x][1][1]) {
memcpy(g[x][3], g[x][2], sizeof(g[x][2]));
memcpy(g[x][2], g[x][1], sizeof(g[x][1]));
g[x][1][1] = z, g[x][1][2] = y;
} else if (z > g[x][2][1]) {
memcpy(g[x][3], g[x][2], sizeof(g[x][2]));
g[x][2][1] = z, g[x][2][2] = y;
} else if (z > g[x][3][1]) {
g[x][3][1] = z, g[x][3][2] = y;
}
}
f[x] = max(c[x][1][1], g[x][1][1] + g[x][2][1]);
}
void dfs2(int x, int father, int cmax, int len) {
if (x != 1) ans = max(ans, f[x] + cmax);
for (int i = Ls[x]; i ; i = e[i].nxt) {
if (e[i].To == father) continue;
int y = e[i].To, a1, a2, a3;
if (g[x][1][2] == y) {
a1 = g[x][2][1];
a2 = g[x][2][1] + g[x][3][1];
} else if (g[x][2][2] == y) {
a1 = g[x][1][1];
a2 = g[x][1][1] + g[x][3][1];
} else {
a1 = g[x][1][1];
a2 = g[x][1][1] + g[x][2][1];
}
if (c[x][1][2] == y) a3 = c[x][2][1];
else a3 = c[x][1][1];
dfs2(y, x, max(max(cmax, a2), max(a3, a1 + len)), max(a1, len) + e[i].w);
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
Addedge(u, v, w);
Addedge(v, u, w);
}
dfs1(1, -1);
ans = f[1];
dfs2(1, -1, 0, 0);
printf("%d\n", ans);
return 0;
}