$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

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;
}
posted @ 2019-10-03 12:01  chc_1234567890  阅读(208)  评论(0编辑  收藏  举报