Polynomial Round 2022 E

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;
}
posted @ 2022-12-24 15:42  ycllz  阅读(20)  评论(0)    收藏  举报