Codeforces 1228

D

直接暴力即可
——Qiyang

E

组合计数dp。
\(dp[i][j]=\sum_{l=0}^{j-1} dp[i-1][l]*k^l*C_{n-l}^{j-l}*(k-1)^{n-l}\)

组合计数水题。
考虑容斥可以做到\(O\left(n^2\right)\)
化一下那个柿子可以做到\(O\left(n\log n\right)\)
——Qiyang

F

大力分类讨论。
有一个显然的事情就是根一定是中心。
然后\(\texttt{check}\)一下就做完了。
注意一下分类的时候一定要仔细有很多叉点。
——Qiyang

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=140003;
int N,n,deg[maxn],b[5],sz[maxn],depth;
vector<int> g[maxn];
void ensure(bool cond){if(!cond){printf("0\n");exit(0);}}
void add(int u,int v){
    ensure(u>=1&&u<=n+1&&v>=1&&v<=n+1);
    g[u].push_back(v);
    g[v].push_back(u);
}
void del(int u,int v){
    ensure(u>=1&&u<=n+1&&v>=1&&v<=n+1);
    g[u].erase(find(g[u].begin(),g[u].end(),v));
    g[v].erase(find(g[v].begin(),g[v].end(),u));
}
int dfs1(int u,int last,int rt){
    if(u==rt)return -1;
    int mx=0,mxi=0;
    sz[u]=1;
    for(int v:g[u]){
        if(v==last)continue;
        if(dfs1(v,u,rt)==-1){
            if(last)return -1;
            else {sz[v]=-1;continue;}
        }
        sz[u]+=sz[v];
        if(sz[v]>mx)mx=sz[v],mxi=v;
    }
    return mxi;
}
int dfs(int u,int last){
    sz[u]=1;
    for(int v:g[u]){
        if(v==last)continue;
        int tmp=dfs(v,u);
        if(tmp){sz[u]=-1;return tmp;}
        sz[u]+=sz[v];
    }
    return sz[u]==(n>>1)?u:0;
}
bool DFS(int u,int last,int dep){
    if(g[u].size()==1&&last){
//printf("leaf\n");
        if(!depth)depth=dep;
        else if(depth!=dep)return 0;
        return 1;
    }
//for(int v:g[u])if(v!=last)printf("%d ",v);puts("");
    if(!((last==0&&g[u].size()==2)||(last&&g[u].size()==3)))return 0;
    for(int v:g[u]){
        if(v==last)continue;
        if(!DFS(v,u,dep+1))return 0;
    }
    return 1;
}
bool check(int u){
//printf("check root:%d\n",u);
    depth=0;
    return DFS(u,0,1);
}
int main(){
    scanf("%d",&N);
    n=(1<<N)-2;
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        deg[u]++,deg[v]++;
    }
    if(n==2){
        printf("2\n1 2");
        return 0;
    }
    for(int i=1;i<=n;i++)b[deg[i]]++;
    if(b[2]==2&&b[4]==0){
        int u1=0,u2=0;
        for(u1=1;u1<=n&&deg[u1]!=2;u1++);
        for(u2=u1+1;u2<=n&&deg[u2]!=2;u2++);
        bool flag=0;
        for(int v:g[u1])if(deg[v]==1){flag=1;break;}
        if(flag)swap(u1,u2);
        add(u2,n+1);
        ensure(check(u1));
        printf("1\n%d",u2);
    }
    else if(b[2]==1&&b[4]==1){
        int u1=0,u2=0,v1=0,v2=0;
        for(u1=1;u1<=n&&deg[u1]!=2;u1++);
        for(u2=1;u2<=n&&deg[u2]!=4;u2++);
        int v3=dfs1(u2,0,u1);
        for(int v:g[u2])if(sz[v]!=-1&&v!=v3)v1==0?(v1=v):(v2=v);
        del(u2,v1);
        del(u2,v2);
        add(u2,n+1);
        add(n+1,v1);
        add(n+1,v2);
        ensure(check(u1));
        printf("1\n%d",u2);
    }
    else if(b[2]==0&&b[4]==0){
        int u1=0,u2=0,v1=0,v2=0;
        for(v1=1;v1<=n&&deg[v1]!=1;v1++);
        u1=dfs(v1,0);
        for(int v:g[u1])if(sz[v]==-1){u2=v;break;}
        v1=0;
        for(int v:g[u1])if(v!=u2)v1==0?(v1=v):(v2=v);
        del(u1,v1);
        del(u1,v2);
        add(u1,n+1);
        add(n+1,v1);
        add(n+1,v2);
        ensure(check(u1));
        printf("2\n%d %d",min(u1,u2),max(u1,u2));
    }
    else ensure(0);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BlogOfchc1234567890/p/11619499.html