求两次直径的高级做法好像已经烂大街了。。
这里贴一下更常规的换根 dp。。
做法就是 Two Paths 多考虑一种情况即可~~
#include <lastweapon/io>
using namespace lastweapon;
const int N = int(3e5) + 9;
int dn[N], up[N]; // 子树内直径,子树外直径
int d[N][4], e[N]; // 子数内 top4 最长距离,子树外最长距离
VI adj[N]; int n, K, z;
void upd(int d[], int v) {
if (v > d[0]) d[3] = d[2], d[2] = d[1], d[1] = d[0], d[0] = v;
else if (v > d[1]) d[3] = d[2], d[2] = d[1], d[1] = v;
else if (v > d[2]) d[3] = d[2], d[2] = v;
else if (v > d[3]) d[3] = v;
}
void dfs1(int u = 1, int p = 0) {
for (auto v: adj[u]) if (v != p) {
dfs1(v, u);
upd(d[u], d[v][0] + 1);
checkMax(dn[u], dn[v]);
}
checkMax(dn[u], d[u][0] + d[u][1]);
}
void dfs2(int u = 1, int p = 0) {
for (auto v: adj[u]) if (v != p) {
checkMax(up[v], up[u]);
checkMax(e[v], e[u] + 1);
int t = d[v][0] + 1;
if (d[u][0] == t) {
checkMax(up[v], d[u][1] + d[u][2]);
checkMax(up[v], d[u][1] + e[u]);
checkMax(e[v], d[u][1] + 1);
}
else {
if (d[u][1] == t) checkMax(up[v], d[u][0] + d[u][2]);
else checkMax(up[v], d[u][0] + d[u][1]);
checkMax(up[v], d[u][0] + e[u]);
checkMax(e[v], d[u][0] + 1);
}
dfs2(v, u);
}
if (K == 2) checkMax(z, dn[u] + up[u]);
upd(d[u], e[u]); checkMax(z, d[u][0] + d[u][1] + (K == 2 ? d[u][2] + d[u][3] : 0));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("/Users/minakokojima/Documents/GitHub/ACM-Training/Workspace/out.txt", "w", stdout);
#endif
RD(n, K); DO(n-1) {
int x, y; RD(x, y);
adj[x].PB(y);
adj[y].PB(x);
}
dfs1(); dfs2();
cout << 2*(n-1) - z + K << endl;
}




Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos
