Topic links: point I ah ╭ (╯ ^ ╰) ╮
Subject to the effect:
Unrooted tree defined
is from tree
to
route points
calculated
,
And from
to
of path
to
path disjoint
Problem-solving ideas:
Compute
, If found to meet
is also satisfied
simply requires that for each
, the largest
can
then
, may be
calculated answer
Consider the path does not intersect, the edges can be enumerated, with this edge to split the tree
and calculating the diameter of two subtrees
and
, corresponding to the above
diameter can be calculated directly subtree tree
,
represents
maximum depth
represents
maximum diameter is selected within a maximum of two subtrees
update to
Then consider how to enumerate the edge, thinking to change the root
in from father
change to
time
first delete
to
side update
information at this time to achieve the purpose of enumeration side
is calculated directly in the process of changing the root of the answer can
change root similar questions:HDU multi-school eighth-field 1006 Acesrc and Travel - tree DP + change root
Core: DP + tree root transducer (enumeration side)
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
#define x first
#define y second
using namespace std;
typedef long long ll;
using pii = pair <int,int>;
const int maxn = 1e5 + 5;
int T, n, dp[maxn][2], mx[maxn];
vector <int> g[maxn];
map <pii, int> m[maxn][2];
map <pii, int>::iterator it;
inline void add0(int u, int v){
m[u][0][{dp[v][0], v}]++;
while(m[u][0].size()>3) m[u][0].erase(m[u][0].begin());
}
inline void add1(int u, int v){
m[u][1][{dp[v][1], v}]++;
while(m[u][1].size()>3) m[u][1].erase(m[u][1].begin());
}
inline void get(int rt){
dp[rt][0] = dp[rt][1] = 1;
if(m[rt][0].size()){
it = m[rt][0].end(), --it;
dp[rt][0] = dp[rt][1] = it->x.x + 1;
if(m[rt][0].size() > 1){
int tmp = it->x.x;
--it;
dp[rt][1] = max(dp[rt][1], tmp + it->x.x + 1);
}
}
if(m[rt][1].size()){
it = m[rt][1].end(), --it;
dp[rt][1] = max(dp[rt][1], it->x.x);
}
}
inline void dfs(int u, int fa){
m[u][0].clear(), m[u][1].clear();
for(auto v : g[u]){
if(v == fa) continue;
dfs(v, u);
add0(u, v);
add1(u, v);
}
get(u);
}
inline void gao(int x, int y){
mx[x] = max(mx[x], y);
mx[y] = max(mx[y], x);
}
inline void move(int rt, int son){
m[rt][0].erase( {dp[son][0], son} );
m[rt][1].erase( {dp[son][1], son} );
get(rt);
gao(dp[rt][1], dp[son][1]);
add0(son, rt);
add1(son, rt);
get(son);
}
inline void dfs1(int rt, int fa){
for(auto son : g[rt]){
if(son == fa) continue;
move(rt, son);
dfs1(son, rt);
move(son, rt);
}
}
int main() {
scanf("%d", &T);
while(T--){
scanf("%d", &n);
memset(mx, 0, sizeof(mx));
for(int i=1; i<=n; i++) g[i].clear();
for(int i=1, u, v; i<n; i++){
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
dfs1(1, 0);
ll ans = 0;
for(int i=n; i; i--) mx[i] = max(mx[i], mx[i+1]), ans += mx[i];
printf("%lld\n", ans);
}
}