div2題目題解:J. Circular Dance

題目:
J. Circular Dance
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
There are n kids, numbered from 1 to n, dancing in a circle around the Christmas tree. Let’s enumerate them in a clockwise direction as p1, p2, …, pn (all these numbers are from 1 to n and are distinct, so p is a permutation). Let the next kid for a kid pi be kid pi+1 if i<n and p1 otherwise. After the dance, each kid remembered two kids: the next kid (let’s call him x) and the next kid for x. Each kid told you which kids he/she remembered: the kid i remembered kids ai,1 and ai,2. However, the order of ai,1 and ai,2 can differ from their order in the circle.

題目圖片地址:
https://espresso.codeforces.com/4b7194b47baa591e9db3cb6908976996d197073d.png

Example: 5 kids in a circle, p=[3,2,4,1,5] (or any cyclic shift). The information kids remembered is: a1,1=3, a1,2=5; a2,1=1, a2,2=4; a3,1=2, a3,2=4; a4,1=1, a4,2=5; a5,1=2, a5,2=3.
You have to restore the order of the kids in the circle using this information. If there are several answers, you may print any. It is guaranteed that at least one solution exists.

If you are Python programmer, consider using PyPy instead of Python when you submit your code.

Input
The first line of the input contains one integer n (3≤n≤2⋅105) — the number of the kids.

The next n lines contain 2 integers each. The i-th line contains two integers ai,1 and ai,2 (1≤ai,1,ai,2≤n,ai,1≠ai,2) — the kids the i-th kid remembered, given in arbitrary order.

Output
Print n integers p1, p2, …, pn — permutation of integers from 1 to n, which corresponds to the order of kids in the circle. If there are several answers, you may print any (for example, it doesn’t matter which kid is the first in the circle). It is guaranteed that at least one solution exists.

Examples
inputCopy
5
3 5
1 4
2 4
1 5
2 3
outputCopy
3 2 4 1 5
inputCopy
3
2 3
3 1
1 2
outputCopy
3 1 2

讀完題目發現這是一個很耍寶的題目,
(爲了簡化題意,他成環我令他方向爲右邊,以下都用右邊代替)
題意是:每個人都會指向他的右邊第一個和第二個人,但是你不知道這個呆逼說的是第一個還是第二個人,反正你知道他右邊兩個人的編號。
比如第一個樣例:1號指向3 5號,就是1號的右邊就是3號和5號,而3號指向了2 4,5號指向了2 3,這時候你知道了3號右邊是2號和四號,並沒有5,所以這個序列是:一定是1 5 3,因爲3右邊沒有5,而5右邊有3;而1右邊一定是3 5,那麼第四個是什麼,5右邊是2 3把,那麼第四個顯然就是除了3的2,同理,第五個就是4,現在訂好了是1 5 3 2 4,這就是答案了;
然後你會問如果是更長的呢?
現在就是關鍵的時候了,數據一定是對的,不會自相矛盾,你隨便找一個點,就以這個起點來看,就是1指向 a,b現在其中一個點是a指向了b,c;a指向了b也就是1 a b c d;
然後我們把1換成d
d指向e,f是不是一直延伸下去了呢 ?
代碼實現:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <queue>
#include <stack>
#include <map>
//鬼畜頭文件
using namespace std;
#define INF 0x3f3f3f3f
#define ULL unsigned long long
#define LL long long
//鬼畜define
 
int all[200010][2];
int n;
//all[i][0]和all[i][1]表示第i個孩子記住的兩個孩子
int ans[200010];
void dfs(int x,int next)
{
	int a=all[x][0];
	int b=all[x][1];
	if(all[a][0]==b)
	{
		if(next<n)ans[next++]=a;
		else return ;
		if(next<n)ans[next++]=b;
		else return ;
		if(next<n)ans[next++]=all[a][1];
		else return ;
		if(all[b][0]==all[a][1])
		{
			if(next<n)ans[next++]=all[b][1];
			else return ;dfs(all[b][1],next);
			return;
		}
		else
		{
			if(next<n)ans[next++]=all[b][0];
			else return ;dfs(all[b][0],next);
			return ;
		}
 
	}
	else if(all[a][1]==b)
	{
		if(next<n)ans[next++]=a;
		else return ;
		if(next<n)ans[next++]=b;
		else return ;
		if(next<n)ans[next++]=all[a][0];
		else return ;
		if(all[b][0]==all[a][0])
		{
			if(next<n)ans[next++]=all[b][1];
			else return ;
			dfs(all[b][1],next);
			return;
		}
		else
		{
			if(next<n)ans[next++]=all[b][0];
			else return ;
			dfs(all[b][0],next);
			return ;
		}
	}
	if(all[b][0]==a)
	{
		if(next<n)ans[next++]=b;
		else return ;
		if(next<n)ans[next++]=a;
		else return ;
		if(next<n)ans[next++]=all[b][1];
		else return ;
		if(all[a][0]==all[b][1])
		{
			if(next<n)ans[next++]=all[a][1];
			else return ;
			dfs(all[a][1],next);
			return;
		}
		else
		{
			if(next<n)ans[next++]=all[a][0];
			else return ;
			dfs(all[a][0],next);
			return ;
		}
	}
	if(all[b][1]==a)
	{
		if(next<n)ans[next++]=b;
		else return ;
		if(next<n)ans[next++]=a;
		else return ;
		if(next<n)ans[next++]=all[b][0];
		else return ;
		if(all[a][1]==all[b][0])
		{
			if(next<n)ans[next++]=all[a][0];
			else return ;
			dfs(all[a][0],next);
			return;
		}
		else
		{
			if(next<n)ans[next++]=all[a][1];
			else return ;
			dfs(all[a][1],next);
			return ;
		}
	}
	return ;
}
int main()
{
	scanf("%d",&n);
	for(int time=0;time<n;time++)
	{
		scanf("%d %d",&all[time][0],&all[time][1]);
		all[time][0]--;
		all[time][1]--;
	}
	//input finished;
	dfs(0,1);
	for(int time=0;time<n;time++)
	{
		printf("%d ",ans[time]+1);
	}
	printf("\n");
 
	return 0;
}

因爲我懶得思考代碼簡潔,然後就暴力枚舉各種情況了,所以很長,但是實際上思路就是上面的那樣,用遞歸的形式找出答案路徑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章