CodeForces 1228F One Node is Gone

Luo Gu title page Portal & codeforces title page Portal

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

\ (n \ LE17 \) .

Title did not say to which point the root, that is, each point are likely to be the root, it is natural to think of a secondary scan and can change the root. Consider a point selected as the root, then obviously meet the parent node of the node to change the conditions of the maximum of the complement of \ (1 \) a. The parent node may be out of the DP.

We will discuss a sub-tree Category:

  1. It is a full binary tree. Its depth is set \ (D \) , wherein the sub-tree Fengyun ordered pair referred to as \ ((0, D) \) . This occurs if and only if it has \ (2 \) subtrees are short and \ (1 \) full binary layer. Particularly, if its size is \ (1 \) , it is characterized by \ ((0,1) \) .
  2. After you restore a full binary tree node. After reduction of the depth provided \ (D \) , the parent node of the node is up \ (X \) , then the note is characterized subtree tree ordered pair \ ((X, D) \) . This occurs if and only if either of the following conditions is true:

    1. Its roots \ (X \) , there are \ (1 \) subtree tree and subtree size \ (1 \) , then the node should change directly complement in complement (X \) \ next.
    2. Its roots \ (X \) , there are \ (3 \) subtree and wherein \ (1 \) trees dwarf \ (1 \) full binary tree layer, the other \ (2 \) trees dwarf \ (2 \) full binary tree layer, then the node should change complement in complement \ (X \) under and \ (2 \) trees short \ (2 \) , the word tree layer is bonded at nodes change complement.
    3. It has \ (2 \) subtree is low and a \ (1 \) layer full binary tree, a complement of another node is a parent \ (X \) after full binary tree nodes.
  3. Whether not fill up the node can not become a full binary tree. It is characterized in mind ordered pair \ ((- 1, -1) \) . Apparently, not satisfied \ (2 \) , compared with this case.

Set \ (dp_i \) is to \ (1 \) is the root to \ (i \) is characterized by sub-root of the tree, the state transition equation is (too difficult to write ♂ hidden). Thus again \ (\ mathrm O (n-2 ^) \) the DFS values of DP can be determined for all nodes. And we want to find the root of all DP value for the root node, this may change with the secondary scanning root, that is, once again DFS. Each node reaches a \ (X \) , the current average DP values of all the nodes are \ (X \) is the root of the whole tree, so if \ (dp_x = (y, n ) (y> 0) \ ) , will be \ (y \) joined the answer sequence. So this time it's to a son \ (s \) was changed to root, then changed only \ (dp_x \) and \ (dp_s \) . We can change what their son collections (involves adding and removing, use setmore convenient), DP re-count value, and then to DFS \ (s \) , this time the whole tree roots \ (s \) a. From \ (S \) when the back, and then restore \ (X \) and \ (S \) son set and DP values, to find other sons. Since the change only needs to change the root \ (2 \)Information of nodes, so complexity is guaranteed, a total of \ (\ mathrm O (n-2 ^ \ ^ n-log_22) = \ mathrm O (2 ^ NN) \) ( \ (\ log \) a set).

Paste the code below:

#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];/*邻接表*/ 
set<int> son[1<<N];/*儿子集合*/
void dfs(int x=1,int fa=0){//求出所有节点的儿子集合 
    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值,即以[1]为根的子树的特征 
void calc_f(int x){//通过儿子集合计算DP值,即那个难写的状态转移方程 
    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){//一遍DFS求出以1为整棵树的根时的DP数组 
    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;//答案序列 
void dfs0(int x=1,int fa=0){//二次扫描 
    if(f[x].X>0)ans.pb(f[x].X);//加入答案序列 
    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);//改变儿子集合,重新算DP值 
        dfs0(y,x);
        son[x].insert(y);son[y].erase(x);calc_f(y);calc_f(x);//还原 
    }
}
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;
}

Guess you like

Origin www.cnblogs.com/ycx-akioi/p/CodeForces-1228F.html