P5022 玄2关求调QMQ
  • 板块灌水区
  • 楼主20090818Cc
  • 当前回复1
  • 已保存回复1
  • 发布时间2025/1/16 20:17
  • 上次更新2025/1/17 09:29:44
查看原帖
P5022 玄2关求调QMQ
1268457
20090818Cc楼主2025/1/16 20:17

有注释

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M=2e6+110;
//全局量 

//快读 
int read(){
	int sum=0,k=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')k=-1;c=getchar();}
	while(c>='0'&&c<='9'){sum=sum*10+c-48;c=getchar();}
	return sum*k;
}

//链式前向星 
struct w{
	int next,to;
	//这一条边是否能走 
	bool cut;
}e[M];
int head[M],k=0;
void add(int u,int v){
	e[++k].next=head[u];
	e[k].to=v;
	head[u]=k;
}



//---------------------------------------------------------------------------------------------------------------------
//  时间戳       tajan 
int time_stamp=0,dfn[M];

//  环上的点集   环的大小     
int ring[M],len=0;

//该点的爹 
int fa[M];

// 该点是否在环上  是否有环 
bool inring[M],ok=false;
void find_ring_dfs(int u,int ft){
	dfn[u]=++time_stamp;
	for(int i=head[u];i;i=e[i].next)
		if(e[i].to!=ft){
			if(dfn[e[i].to]==0){
				fa[e[i].to]=u;
				find_ring_dfs(e[i].to,u);
			}	
			else if(dfn[e[i].to]>=dfn[u]){
				ok=true;
				ring[++len]=u;
				inring[u]=1;
				for(int v=e[i].to;v!=u;v=fa[v]){
					ring[++len]=v;
					inring[v]=1;	
				}
			}
		}
}



//---------------------------------------------------------------------------------------------------------------------
//dfs找最短路 

//二维set某个点可以走到的下一个点的集合 自带排序 
multiset<int>s[50005];

//ans是当前答案,res是最优答案 
int ans[M],res[M],cnt=0;
void ans_dfs(int u,int fa){
	s[u].clear();
	ans[++cnt]=u;
	//走到了u 将u加入当前答案
	
	//u可以走到的下一个位置 
	for(int i=head[u];i;i=e[i].next){
		if(e[i].to!=fa&&e[i].cut==0)//这条边不是断边 
			s[u].insert(e[i].to);
	}
	
	while(!s[u].empty()){
		//去下个地方 
		ans_dfs(*s[u].begin(),u);
		s[u].erase(*s[u].begin());
	}
}



signed main(){
	//读入 
	int n=read(),m=read();
	while(m--){
		//初始化 
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	
	//判断有无环,有环就把环找出来 
	find_ring_dfs(1,0);
	if(ok==0){
		//没有环 从一开始走(字典序max)只有一条路 
		ans_dfs(1,0);
		for(int i=1;i<=cnt;i++)
			printf("%lld ",ans[i]);
	}
	else{
		memset(res,0x3f3f3f3f,sizeof(res));
		//初始设置极大值 
		for(int i=1;i<=len;i++){
			//x是环上一点 
			int x=ring[i],y;
			//y是x为k时的邻边 
			if(x%2==1) y=x+1;
			else y=x-1;
			//枚举该处边为断边 
			e[x].cut=e[y].cut=1;
			//从1开始走 
			ans_dfs(1,0);
			for(int j=1;j<=cnt;j++){
				if(ans[j]<res[j])
					for(int kk=j;kk<=cnt;kk++) res[kk]=ans[kk];
				else if(ans[j]>res[j])break;
				//比较,找字典序最大 
			}
			e[x].cut=e[y].cut=0;
			//回溯 
			memset(ans,0,sizeof(ans));
			cnt=0;
		}
		for(int i=1;i<=n;i++) printf("%lld ",res[i]);
	}
	return 0; 
} 
/*
6 5 
1 3 
2 3 
2 5 
3 4 
4 6
*/

无注释

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M=4e5+110;
int read(){
	int sum=0,k=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')k=-1;c=getchar();}
	while(c>='0'&&c<='9'){sum=sum*10+c-48;c=getchar();}
	return sum*k;
}struct w{int next,to;bool cut;}e[M];
int head[M],k=0;
void add(int u,int v){e[++k].next=head[u];e[k].to=v;head[u]=k;}
int time_stamp=0,dfn[M],ring[M],len=0,fa[M];
bool inring[M],ok=false;
void find_ring_dfs(int u,int ft){
	dfn[u]=++time_stamp;
	for(int i=head[u];i;i=e[i].next) if(e[i].to!=ft)
		if(dfn[e[i].to]==0) fa[e[i].to]=u,find_ring_dfs(e[i].to,u);
		else if(dfn[e[i].to]>=dfn[u]){
			ok=true;
			ring[++len]=u;
			inring[u]=1;
			for(int v=e[i].to;v!=u;v=fa[v]) ring[++len]=v,inring[v]=1;
		}
}
multiset<int>s[50005];
int ans[M],res[M],cnt=0;
void ans_dfs(int u,int fa){

	s[u].clear();
	ans[++cnt]=u;
	for(int i=head[u];i;i=e[i].next){
		
		if(e[i].to!=fa&&e[i].cut==0) s[u].insert(e[i].to);
	}
	while(!s[u].empty()){
		ans_dfs(*s[u].begin(),u);
		s[u].erase(*s[u].begin());
	}
}
signed main(){

	int n=read(),m=read();
	while(m--){
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	find_ring_dfs(1,0);
	if(ok==0){
		ans_dfs(1,0);
		for(int i=1;i<=cnt;i++)printf("%lld ",ans[i]);
	}
	else{
		memset(res,0x3f3f3f3f,sizeof(res));
		for(int i=1;i<=len;i++){
			int x=ring[i],y;
			if(x%2==1) y=x+1;
			else y=x-1;
			e[x].cut=e[y].cut=1;
			ans_dfs(1,0);
			for(int j=1;j<=cnt;j++){
				if(ans[j]<res[j])
					for(int kk=j;kk<=cnt;kk++) res[kk]=ans[kk];
				else if(ans[j]>res[j])break;
			}
			e[x].cut=e[y].cut=0;
			memset(ans,0,sizeof(ans));
			cnt=0;	
		}
		for(int i=1;i<=n;i++) printf("%lld ",res[i]);
	}
	return 0; 
} 
/*
6 5 
1 3 
2 3 
2 5 
3 4 
4 6
*/

感觉脑袋尖尖的,求调

2025/1/16 20:17
加载中...