1. 程式人生 > >【JZOJ5964】【NOIP2018】旅行

【JZOJ5964】【NOIP2018】旅行

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;
}