CodeForces 1228F One Node is Gone

Keywords: C++

Luogu Title Page Portal & CodeForces title page portal

Given a tree(T=(V,E),|V|=2^n-2,|E|=2^n-3, output all \(x), so that there exists a full binary tree\(T'), delete a son of\(x\) and connect all sons of the son to\(x\\\\\\\\\ Output in ascending order.

\(n\le17\).

The title does not say which point is the root, that is, each point may be the root, it is natural to think that it can be scanned and replaced again. First, consider choosing a point as the root. The parent node of the modified node that obviously satisfies the condition has at most (1\\\\\\). This parent node can be DP out.

We will discuss a subtree classification:

  1. It's a full binary tree. Let its depth be (d), then the sub-tree is characterized by ordered pairs ((0,d)). This happens if and only if it has (2) trees and is full of binary trees with low (1\) layers. In particular, if its size is (1), it is characterized by ((0,1)).
  2. Restore a node to a full binary tree. Let the depth of the restored node be(d\) and the parent node of the complemented node be(x\\\), then the character of the subtree is ordered pair((x,d)\). This happens if and only if any of the following conditions are true:

    1. Its root is (x\), there are (1\\) sub-trees and the size of this sub-tree is \\. At this time, the node should be directly added to \\\\.
    2. Its root is \(x\), there is a \\\\\\\\\\\\\\\\\\\\\\Replacement under the node.
    3. It has (2\) sub-trees and a full binary tree with a low (1\) layer. The other one is filled with a full binary tree after a parent node with (x\).
  3. No matter whether the node is filled or not, it cannot be a full binary tree. Remember that it is characterized by ordered pairs (-1, -1)). Obviously, this is the case if you are not satisfied with (1,2).

If u (dp_i) is the characteristic of a subtree with (i) as its root when (1), then the state transition equation is (too hard to write and hidden). This way ( mathrm O (2 ^ n) DFS can calculate the DP value of all nodes. We hope to find the DP value of root node when all nodes are roots, which can be scanned and replaced twice, that is, DFS again. Every time a node(x\) arrives, the DP value of all nodes at present is based on(x\) as the root of the whole tree, so if\(dp_x=(y, n) (y > 0)\, add\(y\) to the answer sequence. At this point, if you want to change one of its sons (s) to the root, then the only changes are (dp_x) and \(dp_s). We can change their son set (which involves adding and deleting, and is more convenient to use set), recalculate the DP value, and then DFS to (s), when the root of the whole tree is (s). When tracing back from (s), restore the set of sons and DP values of (x) and (s) to find other sons. Since the root-changing operation only needs to change the information of (2\) nodes, the complexity is guaranteed. A total of ( mathrm O (2 ^ n log_22 ^ n) =\ mathrm O (2 ^ nn)(\ log\) is set).

Following is the code:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define X first
#define Y second
const int N=17;
int n;
vector<int> nei[1<<N];/*Adjacency list*/ 
set<int> son[1<<N];/*Son collection*/
void dfs(int x=1,int fa=0){//Find the set of sons of all nodes 
    for(int i=0;i<nei[x].size();i++){
        int y=nei[x][i];
        if(y==fa)continue;
        son[x].insert(y);
        dfs(y,x);
    }
}
pair<int,int> f[1<<N];//DP value, i.e. the characteristics of a subtree with [1] as its root 
void calc_f(int x){//Calculate the DP value from the set of sons, that is, the hard-to-write state transition equation 
    if(son[x].size()==0)f[x]=mp(0,1);
    else if(son[x].size()==1)f[x]=f[*son[x].begin()]==mp(0,1)?mp(x,2):mp(-1,-1);
    else if(son[x].size()==2){
        pair<int,int> x1=f[*son[x].begin()],x2=f[*++son[x].begin()];
        if(x1>x2)swap(x1,x2);
        if(!x1.X&&!x2.X)f[x]=x1.Y==x2.Y?mp(0,x1.Y+1):mp(-1,-1);
        else if(!x1.X&&x2.X>0)f[x]=x1.Y==x2.Y?mp(x2.X,x1.Y+1):mp(-1,-1);
        else f[x]=mp(-1,-1);
    }
    else if(son[x].size()==3){
        pair<int,int> x1=f[*son[x].begin()],x2=f[*++son[x].begin()],x3=f[*++ ++son[x].begin()];
        if(x1>x2)swap(x1,x2);if(x2>x3)swap(x2,x3);if(x1>x2)swap(x1,x2);
        if(!x1.X&&!x2.X&&!x3.X)f[x]=x1.Y==x2.Y&&x2.Y+1==x3.Y?mp(x,x3.Y+1):mp(-1,-1);
        else f[x]=mp(-1,-1);
    }
    else f[x]=mp(-1,-1);
//  printf("f[%d]=(%d,%d)\n",x,f[x].X,f[x].Y);
}
void dp(int x=1,int fa=0){//Once DFS finds the DP array with 1 as the root of the whole tree 
    for(int i=0;i<nei[x].size();i++){
        int y=nei[x][i];
        if(y==fa)continue;
        dp(y,x);
    }
    calc_f(x);
}
vector<int> ans;//Answer sequence 
void dfs0(int x=1,int fa=0){//Two scan 
    if(f[x].X>0)ans.pb(f[x].X);//Add a sequence of answers 
    for(int i=0;i<nei[x].size();i++){
        int y=nei[x][i];
        if(y==fa)continue;
        son[x].erase(y);son[y].insert(x);calc_f(x);calc_f(y);//Change son set and recalculate DP value 
        dfs0(y,x);
        son[x].insert(y);son[y].erase(x);calc_f(y);calc_f(x);//reduction 
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=(1<<n)-3;i++){
        int x,y;
        cin>>x>>y;
        nei[x].pb(y);nei[y].pb(x);
    }
    dfs(); 
    dp();
    dfs0();
    cout<<ans.size()<<"\n";
    sort(ans.begin(),ans.end());
    for(int i=0;i<ans.size();i++)cout<<ans[i]<<" ";
    return 0;
}

Posted by SmokyBarnable on Sun, 13 Oct 2019 12:52:38 -0700