E. Two Chess Pieces
题链
我们假设d为无限大的时候
那么就可以将a b分开来看
也就是两个点走过的路径和*2即可
要是有d怎么办呢?
我们可以拆成一条一条链来看
要是a在这条链要走的很远
b只走一小截 那么显然我们的b要衍生到a上面d处
然后我们再计算两个点走过的路径和即可
为了方便我们衍生 我们预处理出来每个点的第d个父亲是谁
这样我们就可以快速求出并且打上标记
dp[i][0/1]就是a/b树中i节点上是否是路径上的点
转移的话
儿子是父亲一定是即可
dp[i]|=dp[v]
int n,d,dp[N][2],a[N],f[N];
//在u号点存在
vector<int>g[N];
void dfs(int u,int fa,int st){
for(auto v:g[u]){
if(v==fa)continue;
dfs(v,u,st);
dp[u][st]|=dp[v][st];
}
}
void get_fa(int u,int fa,int depth){
a[depth]=u;
if(depth>d)f[u]=a[depth-d];
else f[u]=1;
for(auto v:g[u]){
if(v==fa)continue;
get_fa(v,u,depth+1);
}
}
void solve(){
cin>>n>>d;
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
get_fa(1,0,0);
for(int i=0;i<=1;i++){
int m;cin>>m;
for(int j=1;j<=m;j++){
int x;cin>>x;
dp[x][i]=dp[f[x]][i^1]=1;
}
}
dfs(1,0,0);
dfs(1,0,1);
int ans=0;
for(int i=1;i<=n;i++){
ans+=dp[i][0]+dp[i][1];
}
cout<<ans*2-4<<endl;
}
标签:int,dfs,st,fa,depth,2022,Polynomial,Round,dp
From: https://www.cnblogs.com/ycllz/p/17002952.html