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

因为我懒得思考代码简洁,然后就暴力枚举各种情况了,所以很长,但是实际上思路就是上面的那样,用递归的形式找出答案路径

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值