CF1152E--Neko and Flashback(欧拉路径)

题目链接:https://codeforces.com/contest/1152/problem/E

E. Neko and Flashback

Description

A permutation of length k is a sequence of k integers from 1 to k containing each integer exactly once. For example, the sequence [3,1,2] is a permutation of length 3.

When Neko was five, he thought of an array a of n positive integers and a permutation p of length n−1. Then, he performed the following:

Constructed an array b of length n−1, where bi=min(ai,ai+1).
Constructed an array c of length n−1, where ci=max(ai,ai+1).
Constructed an array b′ of length n−1, where b′i=bpi.
Constructed an array c′ of length n−1, where c′i=cpi.
For example, if the array a was [3,4,6,5,7] and permutation p was [2,4,1,3], then Neko would have constructed the following arrays:

b=[3,4,5,5]
c=[4,6,6,7]
b′=[4,5,3,5]
c′=[6,7,4,6]
Then, he wrote two arrays b′ and c′ on a piece of paper and forgot about it. 14 years later, when he was cleaning up his room, he discovered this old piece of paper with two arrays b′ and c′ written on it. However he can’t remember the array a and permutation p he used.

In case Neko made a mistake and there is no array a and permutation p resulting in such b′ and c′, print -1. Otherwise, help him recover any possible array a.

Input

The first line contains an integer n (2≤n≤105) — the number of elements in array a.

The second line contains n−1 integers b′1,b′2,…,b′n−1 (1≤b′i≤109).

The third line contains n−1 integers c′1,c′2,…,c′n−1 (1≤c′i≤109).

Output

If Neko made a mistake and there is no array a and a permutation p leading to the b′ and c′, print -1. Otherwise, print n positive integers ai (1≤ai≤109), denoting the elements of the array a.

If there are multiple possible solutions, print any of them.

Examples

input

5
4 5 3 5
6 7 4 6

output

3 4 6 5 7 

input

3
2 4
3 2

output

-1

input

8
2 3 1 1 2 4 3
3 4 4 2 5 5 4

output

3 4 5 2 1 4 3 2 

Note

The first example is explained is the problem statement.

In the third example, for a=[3,4,5,2,1,4,3,2], a possible permutation p is [7,1,5,4,3,2,6]. In that case, Neko would have constructed the following arrays:

b=[3,4,2,1,1,3,2]
c=[4,5,5,2,4,4,3]
b′=[2,3,1,1,2,4,3]
c′=[3,4,4,2,5,5,4]

题意:

有一个1~n-1的排列p 和数组a,定义bi=min(ai,ai+1),ci=max(ci,ci+1),bi=b[ pi ],ci=c[ pi ],给定b和c,问是否存在原数组a满足给定的数组。

解法:欧拉路径 && 欧拉回路

注:以下内容转载自博客:欧拉回路

1,啥是欧拉路径 && 欧拉回路?

来系统地整理一下有关欧拉回路和欧拉路径的问题。

什么是欧拉路径?在图上用一种走法经过所有的边一次且只有一次的路径叫做欧拉路径。即一笔画。

如果这条路径的起点和终点重合,那么就是欧拉回路。

2,如何判断图是否有欧拉回路或者欧拉路径?

无向图:因为欧拉路径中,除了起点与终点以外,任意点的“进”“出”次数相等,所以除了两个点为奇点(度数为奇数的点)(终点和起点)以外,其它点的度数均为偶数。

如果是欧拉回路,奇点的个数应该为0。

有向图:欧拉路径中,最多只有两个点的入度不等于出度。起点出度比入度大1,终点入度比出度大1。

如果是欧拉回路,所有点的 入度=出度 。

3,寻找欧拉回路或欧拉路径的算法有?

Fluery算法和Hierholzer算法。后者好像也有博客称逐步插入回路法。

后面一种算法无论是编程复杂度还是时间复杂度好像都比前种算法复杂度更优,但前者的应用广泛性好像比后者更高。欧拉回路的更高级的应用还没涉及,如果之后有什么新内容再来补充吧…所以这里就用Hierholzer算法了。

Hierholzer算法自动寻找欧拉回路,在找不到欧拉回路的情况下会找到欧拉路径。前提是得给它指定好起点。

算法流程(无向图):

1.判断奇点数。奇点数若为0则任意指定起点,奇点数若为2则指定起点为奇点。

2.开始递归函数Hierholzer(x):
  循环寻找与x相连的边(x,u):
    删除(x,u)
    删除(u,x)
    Hierholzer(u);
  将x插入答案队列之中

3.倒序输出答案队列


对于该图,算法的执行流程如下:
1.找到该图没有奇点,从1开始进行Hierholzer算法。
2.删边1-2 递归到2
3.删边2-3 递归到3
4.删边3-7 递归到7
5.删边7-1 递归到1
6.1无边,1加入队列,返回
7.7加入队列,返回
8.删边3-4 递归到4
9.删边4-5 递归到5
10.删边5-6 递归到6
11.删边6-3 递归到3
12.3加入队列,返回
13.6加入队列,返回
14.5加入队列,返回
15.4加入队列,返回
16.3加入队列,返回
17.2加入队列,返回
18.1加入队列,返回

答案队列为:1 7 3 6 5 4 3 2 1。反向输出即为答案。

有向图除判断是否存在有一点点不同以外同理。

4,回到本题

首先显然如果bi>ci直接输出-1。如果把bi与ci连一条边(因为相邻),如果能遍历所有边一次且仅一次,那么这个数列就是存在的,对应的数的顺序就是遍历的节点上的数的顺序

由于可能存在重边(样例3),而对于无向图删边的时候需要delete(u,v)同时delete(v,u),所以可以维护一个映射map<int,multiset >,注意multiset 的erase函数使用的时候如果传值,那么multiset中所有相同的元素都会删除,并返回删除的元素的个数,传迭代器只会删除一个改迭代器对应的元素,故本题使用后者。

附代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn=100005;

int n,vertex=0,tot=0,a[maxn],b[maxn];
map<int,multiset<int> > vec;
map<int,multiset<int> >::iterator it;
map<int,int> vis;
vector<int> ans;

//Hierholzer算法
void hierholzer(int cur)
{
	while(vec[cur].size()){
		int i=*(vec[cur].begin());
		vec[cur].erase(vec[cur].begin());
		vec[i].erase(vec[i].find(cur));
		hierholzer(i);
	}
	ans.push_back(cur);
}

void dfs(int cur)
{
	if(!vis.count(cur)){
		vis[cur]=1;
		tot++;
	}else return;
	for(auto j:vec[cur]){
		dfs(j);
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++) scanf("%d",&a[i]);
	for(int i=1;i<n;i++) scanf("%d",&b[i]);

	for(int i=1;i<n;i++){
		if(a[i]>b[i]) return printf("-1\n"),0;
		vec[a[i]].insert(b[i]);
		vec[b[i]].insert(a[i]);
	}
	vertex=vec.size();

	//判断联通
	int odd=0,sta=(vec.begin())->first;
	dfs(sta);
	if(tot!=vertex) return printf("-1\n"),0;

	//找到奇数度数的点作为头结点
	for(it=vec.begin();it!=vec.end();it++) if((it->second).size()%2) {
		odd++;
		sta=it->first;
	}

	//奇度数点只能是0个或2个
	if(odd!=0&&odd!=2) return printf("-1\n"),0;
	
	hierholzer(sta);

	//这个判断好像可以不要?
	if(ans.size()!=n) return printf("-1\n"),0;
	for(auto i:ans) printf("%d ",i);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值