题目大意:
给定一颗树,求这个树的最大子树,且这个子树是一个good-tree。
good-tree的定义是:每个节点可以表示成一个数值区间,而树上的边表示两个点表示的数值区间相交
解题思路:
- 根据线段相交,假设以 r o o t root root节点为根,那么我们可以选择两条棵子树进行向下递归继续选择,其他的儿子节点只能选自己,因为线段只有两端向外延伸
- 如果不是根节点那么我们只能选一个子树向下延伸,其他都是只能直接选儿子
- 那么我们就是要枚举所以点为根去dp,然后更新答案
- 但是这样会超时,那么我们就要进行换根dp!
- 我们看看要保存什么记录?
- 对于每个点我们要记录下面的最大值和次大值的子树,那么我们就选这两个子树进行延伸,其他就直接选。
- 换根的时候我们要看看看当前点和根节点之间的关系?
- 如果根节点的最大值和次大值里面有一个来着你,那么你就选另一个!
- 然后再更新你自己的次大值和最大值就可以了
AC code
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 500010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
template<typename T> void read(T &x) {
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {
read(first);
read(args...);
}
vector<int> G[maxn];
int dp[maxn], n;
int ans;
pii inf[maxn];
void dfs1(int u, int fa) {
inf[u] = {0,0};// inf[u].first 记录最大值,second 记录次大值
for(auto it : G[u]) {
if(it == fa) continue;
dfs1(it,u);
if(dp[it] > inf[u].first) inf[u].second = inf[u].first, inf[u].first = dp[it];
else if(dp[it] > inf[u].second) inf[u].second = dp[it];
}
// max 部分算的是不向下延伸的子树的个数 除了根节点都不加次大值
dp[u] = max((int)G[u].size()-2,0)+inf[u].first+inf[u].second*(u==1)+1;
}
void dfs2(int u, int fa) {
if(u != 1) {
int maxf = (inf[fa].first == dp[u]) ? inf[fa].second : inf[fa].first;
maxf = maxf + max((int)G[fa].size()-2,0)+1; // fa变成子树的贡献
// 更新
if(maxf > inf[u].first) inf[u].second = inf[u].first, inf[u].first = maxf;
else if(maxf > inf[u].second) inf[u].second = maxf;
dp[u] = max((int)G[u].size()-2,0)+inf[u].first+inf[u].second+1;
}
ans = max(ans,dp[u]);
for(auto it : G[u]) {
if(it == fa) continue;
dfs2(it,u);
}
}
int main() {
IOS;
int T;
cin >> T;
while(T --) {
cin >> n;
for(int i = 1; i <= n; ++ i) G[i].clear();
for(int i = 1; i < n; ++ i) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(1,0);
dfs2(1,0);
cout << ans << endl;
ans = 0;
}
}