【JZOJ5964】【NOIP2018】旅行

版权声明:欢迎dalao指出错误暴踩本SD,蒟蒻写的博客转载也要吱一声 https://blog.csdn.net/enjoy_pascal/article/details/84329998

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 + 1 n==m+1 1 1 号点 O ( n 2 ) O(n^2) 走出 d f s dfs 序就行了

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

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

  • 于是 O ( n m ) 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;
}

猜你喜欢

转载自blog.csdn.net/enjoy_pascal/article/details/84329998