欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【JZOJ5964】【NOIP2018】旅行

程序员文章站 2024-03-20 11:12:28
...

description

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


analysis

  • n==m+1n==m+111号点O(n2)O(n^2)走出dfsdfs序就行了

  • n==mn==m的话O(m)O(m)枚举哪一条树边不能走

  • 暴力O(n2m)O(n^2m)不能接受,但是可以先排序预处理,均摊不超O(nlog2n)O(nlog_2n)

  • 于是O(nm)O(nm)记录最小字典序的答案即可


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 5005
#define fo(i,a,b) for (int i=a;i<=b;++i)
#define fd(i,a,b) for (int i=a;i>=b;--i)
#define rep(i,a) for (int i=last[a];i;i=next[i])
#define O3 __attribute__((optimize("-O3")))

using namespace std;

int f[MAXN][MAXN],gx[MAXN],gy[MAXN],ans[MAXN],answer[MAXN];
bool b[MAXN][MAXN],bz[MAXN];
int n,m,tot,pos;

O3 inline int max(int x,int y)
{
	return x>y?x:y;
}
O3 inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
O3 inline void dfs(int x)
{
	printf("%d ",x),bz[x]=0;
	fo(i,1,n)if (b[x][i] && bz[i])dfs(i);
}
O3 inline void dfs1(int x)
{
	ans[++pos]=x,bz[x]=0;
	fo(i,1,f[x][0])if (b[x][f[x][i]] && bz[f[x][i]])dfs1(f[x][i]);
}
O3 inline bool judge()
{
	fo(i,1,n)
	{
		if (ans[i]<answer[i])return 1;
		else if (ans[i]>answer[i])return 0;
	}
	return 0;
}
O3 int main()
{
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout);
	n=read(),m=read();
	fo(i,1,m)
	{
		int x=read(),y=read();
		gx[i]=x,gy[i]=y;
		b[x][y]=b[y][x]=1;
		f[x][++f[x][0]]=y,f[y][++f[y][0]]=x;
	}
	if (n==m+1)
	{
		memset(bz,1,sizeof(bz));
		dfs(1);
		printf("\n");
		return 0;
	}
	fo(i,1,n)sort(f[i]+1,f[i]+f[i][0]+1),answer[i]=1000000007;
	fo(i,1,m)
	{
		memset(bz,1,sizeof(bz));
		int x=gx[i],y=gy[i];
		b[x][y]=b[y][x]=pos=0;
		dfs1(1);
		if (judge())memcpy(answer,ans,sizeof(answer));
		b[x][y]=b[y][x]=1;
	}
	fo(i,1,n)printf("%d ",answer[i]);
	printf("\n");
	return 0;
}
相关标签: NOIP dfs