CF1338D Nested Rubber Bands

考虑答案在树上长什么样子。

首先答案肯定是一个独立集,因为两两之间没有交。

对于相邻两个圆,他一定是经过中间一个点来连接的,画个图容易发现中间的这个点连接的所有点都能加入答案。

也就是说答案应该是树上一条形如毛毛虫一样的独立集,就是树上的一条链加上每个点周围的点。

这个就可以用类似最大独立集的 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);
}
posted @ 2022-09-07 09:02  CelticOIer  阅读(25)  评论(0编辑  收藏  举报