AT_agc018_f [AGC018F] Two Trees 题解

link

先考虑怎么判断无解。对于一个点,它的儿子的子树和要么是 \(1\) 要么是 \(-1\),这两个值都为奇数,所以如果一个点在左树和右数的儿子数的奇偶性不同,那么肯定是无解的。

我们在两棵树的根上面连一条边,我们称之为根边。对于一个度数为奇数的点(根边也要参与度数统计),我们将它在两棵树上的点连一条边,我们称之为横边。这样就得到了一个度数全部为偶数的图。

我们在上面跑欧拉回路进行定向,如果一个横边的方向是从左到右,我们就把这个点(横边连接的两个点实际上是同一个点)权值设为 \(1\),反之我们就把这个点权值设为 \(-1\)

下面是对于正确性的证明:

我们把欧拉回路拆成若干个环。

对于一个环,它要么经过两条横边,要么经过一条横边和根边。

考虑一个点 \(i\),对于经过的两条横边都在 \(i\) 的子树内的环,这种环对 \(i\) 的子树和的贡献恰好自己抵消了。

对于经过的一条横边在 \(i\) 的子树里的环,这种环对 \(i\) 的子树和的贡献是 \(1\)\(-1\)。并且这种环一定有且只有一个,因为每一个这种环肯定会经过 \(i\) 和父亲这条边,而 \(i\) 和父亲这条边对于非根的点有且只有一个,对于根虽然没有父亲,但是我们也建立了根边。

这也就解释了为什么需要根边,它相当于对两棵树的根建了一个虚拟根,使得它们也有了父亲。如果没有根边,我们跑出来的方案中根的子树和就会变成 \(0\)

这样我们就能够保证每个点的子树和一定为 \(1\)\(-1\) 了。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int n,rt1,rt2,now[N],ans[N],idx;bool f=1,vis[N];
vector<pair<int,int> > e[N];
void dfs(int x){
    while(!e[x].empty()){
        auto v=e[x].back();e[x].pop_back();
        if(vis[v.second])continue;
        vis[v.second]=1;
        if(((x==rt1&&v.first==rt2)||(x==rt2&&v.first==rt1))&&f) f=0;
        else if(x<=n&&v.first>n) ans[x]++;
        else if(x>n&&v.first<=n) ans[v.first]--;
        dfs(v.first);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        int fa;cin>>fa;
        if(fa<0){
            rt1=i;
            continue;
        }
        e[i].push_back({fa,++idx});
        e[fa].push_back({i,idx});
    }
    for(int i=1;i<=n;i++){
        int fa;cin>>fa;
        if(fa<0){
            rt2=i+n;
            continue;
        }
        e[i+n].push_back({fa+n,++idx});
        e[fa+n].push_back({i+n,idx});
    }
    e[rt1].push_back({rt2,++idx});
    e[rt2].push_back({rt1,idx});
    for(int i=1;i<=n;i++){
        if((e[i].size()+e[i+n].size())&1){
            cout<<"IMPOSSIBLE\n";
            return 0;
        }
        if(e[i].size()&1){
            e[i].push_back({i+n,++idx});
            e[i+n].push_back({i,idx});
        }
    }
    dfs(rt1);
    cout<<"POSSIBLE\n";
    for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
    return 0;
}
posted @ 2026-09-05 17:38  cqbzcjh  阅读(4)  评论(0)    收藏  举报