列表

详情


NC21473. [NOIP2018]旅行

描述

小 Y 是一个爱好旅行的 OIer。她来到 X 国,打算将各个城市都玩一遍。
小 Y 了解到,X 国的 𝑛 个城市之间有 𝑚 条双向道路。每条双向道路连接两个城市。 不存在两条连接同一对城市的道路,也不存在一条连接一个城市和它本身的道路。并且, 从任意一个城市出发,通过这些道路都可以到达任意一个其他城市。小 Y 只能通过这些 道路从一个城市前往另一个城市。
小 Y 的旅行方案是这样的:任意选定一个城市作为起点,然后从起点开始,每次可 以选择一条与当前城市相连的道路,走向一个没有去过的城市,或者沿着第一次访问该 城市时经过的道路后退到上一个城市。当小 Y 回到起点时,她可以选择结束这次旅行或 继续旅行。需要注意的是,小 Y 要求在旅行方案中,每个城市都被访问到。
为了让自己的旅行更有意义,小 Y 决定在每到达一个新的城市(包括起点)时,将 它的编号记录下来。她知道这样会形成一个长度为 𝑛 的序列。她希望这个序列的字典序 最小,你能帮帮她吗?
对于两个长度均为 𝑛 的序列 A 和 B,当且仅当存在一个正整数 x,满足以下条件时, 我们说序列 A 的字典序小于 B。
1.对于任意正整数1≤i<x,序列A的第i个元素Ai 和序列B的第i个元素 Bi 相同。
2. 序列A的第 x 个元素的值小于序列B的第 x 个元素的值。

输入描述

输入文件共 𝑚 + 1 行。第一行包含两个整数 𝑛, 𝑚(𝑚 ≤ 𝑛) ,中间用一个空格分隔。
接下来 𝑚 行,每行包含两个整数 𝑢, 𝑣 (1 ≤ 𝑢, 𝑣 ≤ 𝑛) ,表示编号为 𝑢 和 𝑣 的城市之 间有一条道路,两个整数之间用一个空格分隔。

输出描述

输出文件包含一行, 𝑛 个整数,表示字典序最小的序列。相邻两个整数之间用一个 空格分隔。

示例1

输入:

6 5
1 3
2 3
2 5
3 4
4 6

输出:

1 3 2 5 4 6

示例2

输入:

6 6
1 3
2 3
2 5
3 4
4 5
4 6

输出:

1 3 2 4 5 6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 545ms, 内存消耗: 36192K, 提交时间: 2019-10-22 16:43:15

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
int n,m;
int X[maxn],Y[maxn],g[maxn][maxn],ans[maxn],ans1[maxn];
int visit[maxn],cnt=0,ok=0;

void dfs1(int x ){
	visit[x]=1;
	ans[++cnt]=x;
	for(int i=1;i<=n;i++){
		if(visit[i]==0 && g[x][i]==1) {
		dfs1(i);
		}
	}
    return ;
}

int dfs2(int x){
	if(x>ans[cnt+1] && (ok==0)) return 0;
	if(x<ans[cnt+1]) ok=1;
	visit[x]=1;
	ans1[++cnt]=x;
	for(int i=1;i<=n;i++){
		if((g[x][i]==1) && (visit[i]==0 )) {
		if(dfs2(i)==0) return 0;
		}
	}
    return 1 ;
}

void solve() {
	for(int i=1;i<=n;i++) ans[i]=n;
	for(int i=0;i<m;i++){
		int x=X[i],y=Y[i];
		memset(visit,0,sizeof(visit));
		cnt=0;ok=0;
		g[x][y]=0;g[y][x]=0;
		dfs2(1);
		g[x][y]=1;g[y][x]=1;
		if(cnt==n){for(int i=1;i<=n;i++) ans[i]=ans1[i];	} 		
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		X[i]=x;Y[i]=y;
		g[x][y]=g[y][x]=1;
	}
	memset(ans,0x3f,sizeof(ans));
	if(m==n-1) dfs1(1);
	else solve();
	
	cout<<ans[1];
    for(int i=2;i<=n;i++) 
	{cout<<" "<<ans[i]; }
    cout<<endl;
    
	return 0;
} 

C++(clang++ 11.0.1) 解法, 执行用时: 13ms, 内存消耗: 952K, 提交时间: 2022-08-09 11:06:45

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+10;
int vis[N],l[N],r[N],u,v,cnt,tr;
vector<int>g[N],s(N),ans(N,N);
int dfs(int id){
	if(tr){
		if(id>ans[cnt])return 1;
		if(id<ans[cnt])tr=0;
	}
	vis[id]=1;
	s[cnt++]=id;
	for(int i:g[id]){
		if(!vis[i]&&!(i==u&&id==v)&&!(i==v&&id==u)){
			if(dfs(i))return 1;
		}
	}
	return 0;
}
void solve(){
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		cin>>l[i]>>r[i];
		g[l[i]].push_back(r[i]);
		g[r[i]].push_back(l[i]);
	}
	for(int i=1;i<=n;i++)sort(g[i].begin(),g[i].end());
	if(n==m+1){
		dfs(1);
		for(int i=0;i<n;i++)printf("%d ",s[i]);
		return;
	}
	for(int i=0;i<m;i++){
		memset(vis,0,sizeof vis);
		cnt=0,tr=1;
		u=l[i],v=r[i];
		dfs(1);
		if(cnt==n)ans=s;
	}
	for(int i=0;i<n;i++)printf("%d ",ans[i]);
}
int main(){
	int t=1;
	while(t--)solve();
	return 0;
}

上一题