[DP记录]AT2268 [AGC008F] Black Radius
command_block · · 个人记录
题意 : 给出一颗
定义树上邻域
令
先统计所有
这样,对于同一个
若
先观察怎样的
对于同一个关键点
首先我们要求
此外,考虑同构。以
显然,除了
若
(如图,蓝色点为选择的
设
则有
这也说明了,对于某个
现在,要对每个关键点
不难发现,这里的
而所有
-
S\neq T
在
考虑对于非关键点
以
不难发现,当
于是,下界即为 : 覆盖某个含关键点的分支所需的最小
也可以使用
知道了各个
#include<algorithm>
#include<cstdio>
#include<vector>
#define pb push_back
#define MaxN 200500
using namespace std;
const int INF=1000000000;
vector<int> g[MaxN];
char fl[MaxN];
int len[MaxN],fa[MaxN],siz[MaxN];
void dfs1(int u,int _f)
{
fa[u]=_f;
siz[u]=fl[u];
for (int i=0,v;i<g[u].size();i++)
if ((v=g[u][i])!=_f){
dfs1(v,u);
len[u]=max(len[u],len[v]+1);
siz[u]+=siz[v];
}
}
int flen[MaxN];
void dfs2(int u,int l)
{
flen[u]=l;
int p1=-1,x1=-1,x2=-1;
for (int i=0;i<g[u].size();i++)
if (g[u][i]!=fa[u])
if (len[g[u][i]]>x1)
{x2=x1;x1=len[g[u][p1=i]];}
else x2=max(x2,len[g[u][i]]);
for (int i=0;i<g[u].size();i++)
if (g[u][i]!=fa[u])
dfs2(g[u][i],max((i==p1 ? x2 : x1)+2,l+1));
}
int n;
int main()
{
scanf("%d",&n);
for (int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
g[u].pb(v);g[v].pb(u);
}scanf("%s",fl+1);
for (int i=1;i<=n;i++)fl[i]-='0';
dfs1(1,0);dfs2(1,0);
long long ans=0;
for (int u=1;u<=n;u++){
int x1=0,x2=0;
for (int i=0;i<g[u].size();i++)
if (g[u][i]!=fa[u])
if (len[g[u][i]]+1>x1)
{x2=x1;x1=len[g[u][i]]+1;}
else x2=max(x2,len[g[u][i]]+1);
if (flen[u]){
if (flen[u]>x1)
{x2=x1;x1=flen[u];}
else x2=max(x2,flen[u]);
}
int tr=max(0,min(x2+1,max(len[u],flen[u])-1)),tl=n+1;
if (fl[u])tl=0;
for (int i=0;i<g[u].size();i++)
if (g[u][i]!=fa[u]&&siz[g[u][i]])
tl=min(tl,len[g[u][i]]+1);
if (fa[u]&&siz[1]-siz[u]>0)
tl=min(tl,flen[u]);
ans+=(tl<=tr ? tr-tl+1 : 0);
}printf("%lld",ans+1);
return 0;
}