题目
思路来源
乱搞ac
题解
注意到提出一个点之后, 后面第二次提出的点、第三次提出的点,
如果后续成为叶子,一定不相邻,所以等价于求原树的最大独立集
但是第一次提出的叶子可以和第二次提出的叶子相邻
这个看最后一个样例就可以了,这个样例给的很好,手玩一下就知道了
于是,换根dp维护[u是不是叶子]+u为根时的最大独立集大小,dp[u][2]选不选+换根
枚举每个点是不是根即可
代码
#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,ll> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
typedef long long ll;
const int N=2e5+10;
int t,n,u,v,dp[N][2],ans[N][2];//换根+dp[i][2]选不选最大独立集
vector<int>e[N];
void dfs(int u,int fa){dp[u][0]=0;dp[u][1]=1;for(auto &v:e[u]){if(v==fa)continue;dfs(v,u);dp[u][0]+=max(dp[v][0],dp[v][1]);dp[u][1]+=dp[v][0];}
}
void dfs2(int u,int fa){rep(i,0,1)ans[u][i]=dp[u][i];for(auto &v:e[u]){if(v==fa)continue;dp[u][0]-=max(dp[v][0],dp[v][1]);dp[u][1]-=dp[v][0];dp[v][0]+=max(dp[u][0],dp[u][1]);dp[v][1]+=dp[u][0];dfs2(v,u);dp[v][0]-=max(dp[u][0],dp[u][1]);dp[v][1]-=dp[u][0];dp[u][0]+=max(dp[v][0],dp[v][1]);dp[u][1]+=dp[v][0];}
}
int sol(){dfs(1,0);dfs2(1,0);int res=0;rep(i,1,n){bool ok=SZ(e[i])==1;res=max(res,ans[i][0]+ok);res=max(res,ans[i][1]);}return res;
}
int main(){sci(t);while(t--){sci(n);rep(i,1,n)e[i].clear();rep(i,1,n-1){dp[u][0]=dp[u][1]=0;sci(u),sci(v);e[u].pb(v),e[v].pb(u);}pte(sol());}return 0;
}