题解:P14260 期待(counting)
VinstaG173 · · 题解
tag:树形结构,计数。
以下为了表述方便,称期待的方案为合法。
暴力
直接枚举所有合法移动方案,复杂度
特殊性质 B
祖传不按顺序讲特殊性质。
菊花图部分分。
事实上发现在菊花图上只有四种本质不同的情况,直接求出对应答案公式即可。
若
复杂度
特殊性质 C
链部分分。不妨设
首先考虑合法移动方案的条件。样例非常良心地给我们提示了一种小 corner case:在一条边上两端点互换。容易发现只有这一种情况可以使得两棋子移动方向不同。以下不再赘述。
发现其余情况下只要两棋子移动方向相同则方案合法。再根据非常良心的样例解释容易发现除了
如上我们将问题转化为:求区间组
直接枚举
考虑
不妨设
特殊性质 A
完全二叉树的大部分性质我不知道怎么用。这个部分分是正解的一部分。
容易证明合法移动方案中经过的所有点一定在同一条链上。只要确定这条链就可以沿用链部分分的解法。
考虑以
正解
同完全二叉树部分分直接算可以做到
Code:
int n,y,s;
int d[100003];
vector<int>e[100003];
int c0[100003];
int c1[100003];
int dep[100003],dp0,dp1;
void dfs(int u,int fa){
for(int i=0,v;i<d[u];++i){
v=e[u][i];if(v==fa)continue;
dep[v]=dep[u]+1;dp0=max(dp0,dep[v]);
++c0[dep[v]];dfs(v,u);
}
}
int dis;
void dfs1(int u,int fa){
if(u==s){
dis=dep[u];
dep[u]=dp0=0;
c0[0]=1;dfs(u,fa);
return;
}for(int i=0,v;i<d[u];++i){
v=e[u][i];if(v==fa)continue;
dep[v]=dep[u]+1;dfs1(v,u);
}
}
ll ans;
inline void solve(){
cin>>n>>y>>s;ans=0;
for(int i=1;i<=n;++i){
d[i]=0;e[i].clear();
}for(int i=1,u,v;i<n;++i){
cin>>u>>v;++d[u],++d[v];
e[u].push_back(v);
e[v].push_back(u);
}dep[y]=0;dfs1(y,0);
for(int i=0;i<=dp0;++i)
c1[i]=c0[i],c0[i]=0;
dp1=dp0;swap(y,s);
dep[y]=0;dfs1(y,0);
for(int i=max(dp0,dp1);i>=0;--i)
ans+=((ll)c0[i]*c1[i+1]+(ll)c1[i]*c0[i+1]+(ll)c0[i]*c1[i])*(dis+i*2+1),\
c0[i]+=c0[i+1],c1[i]+=c1[i+1];
ans=ans*2-1;if(dis==1)ans+=2;
for(int i=0;i<=n;++i)c0[i]=c1[i]=0;
cout<<ans<<"\n";
}