LGP5049题解

无内鬼,来个线性做法

发现是一个 sb 贪心,只需要保证下一个去的节点尽量小即可。

问题分为三个阶段:在一颗“子树”内,在环上,在别的“子树”内。(环上每个节点挂着一堆子树)

首先肯定从 \(1\) 开始搜。尽量走小的地方。

走到环上后需要决定走哪个方向,这个很容易。

在环上某个位置需要判定是否停下来,判断一下如果不向前走的话,序列的下一个位置会是多少即可。

然后细节差不多就是这些了。。。在别的子树内很容易实现。

但是需要对节点排序,挂在 vector 上然后扫一遍往回插入即可。

#include<algorithm>
#include<cstdio>
#include<vector>
const int M=5e5+5;
int n,m,f[M];std::vector<int>G[M],id[M];bool vis[M],inr[M];int top,stk[M];
int x[M],y[M];
inline int min(const int&a,const int&b){
	return a>b?b:a;
}
inline void SolveTree(const int&u){
	printf("%d ",u);
	vis[u]=true;for(int&v:G[u])if(!vis[v])SolveTree(v);
}
inline void SolveRing(const int&u,const int&V,const bool&typ){
	printf("%d ",u);
	vis[u]=true;
	for(int v,i=0;i<G[u].size();++i)if(!vis[v=G[u][i]]){
		if(inr[v]&&(typ||v<V||(i+1==G[u].size()?false:i+1+vis[G[u][i+1]]!=G[u].size()))){
			SolveRing(v,i+1==G[u].size()?V:vis[G[u][i+1]]?i+2==G[u].size()?V:G[u][i+2]:G[u][i+1],typ);
		}
		if(!inr[v])SolveTree(v);
	}
}
inline void SolveBegin(const int&u){
	printf("%d ",u);
	vis[u]=true;
	if(inr[u]){
		bool typ(false);
		for(int v,i=0;i<G[u].size();++i)if(!vis[v=G[u][i]]){
			if(inr[v])SolveRing(v,typ?n+1:G[u][i+1],typ),typ=true;
			else SolveBegin(v);
		}
	}
	else for(int&v:G[u])if(!vis[v])SolveBegin(v);
}
inline bool FindRing(const int&u){
	stk[++top]=u;
	for(int&v:G[u])if(v^f[u]){
		if(f[v]){
			do inr[stk[top]]=true;while(stk[top--]^v);return f[u]=0,true;
		}
		f[v]=u;if(FindRing(v))return f[u]=0,true;
	}
	return --top,f[u]=0,false;
}
signed main(){
	scanf("%d%d",&n,&m);
	for(int u,v,i=1;i<=m;++i)scanf("%d%d",&u,&v),id[v].push_back(u),id[u].push_back(v);
	for(int u=1;u<=n;++u)for(int&v:id[u])G[v].push_back(u);FindRing(1);SolveBegin(1);
}
posted @ 2022-04-06 14:24  Prean  阅读(20)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};