uoj#339. 【清华集训2017】小 Y 和二叉树(构造)

传送门

膜拜大米饼巨巨

构造思路太神仙了……

先考虑这个序列的开头,肯定是一个度数小于等于(2)且标号最小的节点,设为(u)

如果一个点度数小于等于(2),我们称这个点可以被选择,一个点的(mn)为它的子树中(不包括子树的根)能被选择的点中最小的标号

那么如果能够确定根节点,只要从根节点往下(dfs),然后每次贪心的选择(mn)小的那个节点就好了

为了找到根节点,我们从(u)开始往下(dfs),先预处理出以(u)为根时所有节点的(mn),那么每一次往下走的时候,只要判断一下走了之后会不会使中序遍历变得更劣,如果不会的话往下走,否则就停在这里,这个就是根节点了

然后从根节点贪心(dfs)一遍就可以得出答案了

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
const int N=1e6+5;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int mn[N],ls[N],rs[N],ch[N][2],deg[N];
int n,st,rt,u,v;
void dfs1(int u,int fa){
	int cnt=0;
	go(u)if(v!=fa){
		ch[u][cnt++]=v,dfs1(v,u);
		cmin(mn[u],mn[v]);
	}
}
void dfs2(int u){
	if(!ch[u][0])return rt=u,void();
	if(!ch[u][1]){
		if(ch[u][0]<mn[ch[u][0]])dfs2(ch[u][0]);
		else return rt=u,void();
	}else dfs2(mn[ch[u][0]]<mn[ch[u][1]]?ch[u][1]:ch[u][0]);
}
int dfs3(int u,int fa){
	if(deg[u]==1&&u!=rt)return u;
	int res=n+1,now;if(u==rt&&deg[u]==1||u!=rt&&deg[u]==2)res=u;
	go(u)if(v!=fa){
		now=dfs3(v,u);
		if(now<res)rs[u]=ls[u],ls[u]=v,res=now;
		else rs[u]=v;
	}return res;
}
void dfs4(int u){
	if(ls[u])dfs4(ls[u]);
	print(u);
	if(rs[u])dfs4(rs[u]);
}
int main(){
//	freopen("testdata.in","r",stdin);
	n=read(),st=n+1;
	fp(i,1,n){
		deg[i]=read(),mn[i]=n+1;
		fp(j,1,deg[i])u=read(),add(i,u);
		if(deg[i]<=2)mn[i]=i,cmin(st,i);
	}
	dfs1(st,0),dfs2(st),dfs3(rt,0),dfs4(rt);
//	fp(i,1,n)printf("%d %d %d
",i,ls[i],rs[i]);
	return Ot(),0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10273322.html