考虑答案在树上长什么样子。
首先答案肯定是一个独立集,因为两两之间没有交。
对于相邻两个圆,他一定是经过中间一个点来连接的,画个图容易发现中间的这个点连接的所有点都能加入答案。
也就是说答案应该是树上一条形如毛毛虫一样的独立集,就是树上的一条链加上每个点周围的点。
这个就可以用类似最大独立集的 dp 来维护,在合并父亲和儿子的 dp 以及计算完一个点的 dp 值时统计答案即可。
具体见代码。
#include<bits/stdc++.h>
#define N 2001001
#define MAX 3005
#define eps 1e-10
using namespace std;
typedef long long ll;
typedef double db;
const db PI=acos(-1);
const ll mod=998244353,inv2=(mod+1)/2,inf=1e18,inv3=(mod+1)/3;
inline void read(ll &ret)
{
ret=0;char c=getchar();bool pd=false;
while(!isdigit(c)){pd|=c=='-';c=getchar();}
while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c&15);c=getchar();}
ret=pd?-ret:ret;
return;
}
ll n,x,y,ans;
vector<ll>v[N];
ll f[N][2];
inline void dfs(ll ver,ll fa)
{
f[ver][1]=1;
for(int i=0;i<v[ver].size();i++)
{
ll to=v[ver][i];
if(to==fa)
continue;
dfs(to,ver);
ans=max(ans,f[ver][1]+f[to][0]);
ans=max(ans,f[ver][0]+max(f[to][0],f[to][1])+(ll)v[ver].size()-2);
f[ver][0]=max({f[to][0],f[to][1],f[ver][0]});
f[ver][1]=max(f[to][0]+1,f[ver][1]);
}
ans=max(ans,max(f[ver][0],f[ver][1]));
f[ver][0]=max(f[ver][0],f[ver][0]+(ll)v[ver].size()-2);
return;
}
signed main()
{
read(n);
for(int i=1;i<n;i++)
{
read(x);
read(y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
printf("%lld\n",ans);
exit(0);
}
标签:Bands,ll,ret,Rubber,答案,define,CF1338D,dp,mod
From: https://www.cnblogs.com/CelticBlog/p/16664071.html