LG 题解 CF1152E Neko and Flashback
Description
题目翻译好像有点问题,应该改为,
\[b_i = \min \{a_i, a_{i+1} \}
\]
\[c_i = \max \{a_i, a_{i+1} \}
\]
Solution
先说做法,欧拉路径。
如果不知道什么是欧拉路径,可以去看一下这个模板题。
其实这个做法通过观察样例就能看出来。
其实 \(p\) 序列没啥用,唯一的用处就是让你可以打乱这个 \(b,c\) 序列,实现过程中不需要考虑它。
考虑欧拉回路正确性,对于一对 \(b_i, c_i\),一定分别对应着 \(a_i,a_{i+1}\) 的两个值,可以看做是两个点连边,而 \(b_{i+1}\) 和 \(c_{i+1}\) 又能将 \(a_{i+1}\) 和 \(a_{i+2}\) 连接。最后整个 \(a\) 序列就是一条由每一对 \(b_i,c_i\) 连起来的合法的欧拉路径。
对了,虽然 \(b,c\) 序列的值域是 \(10^9\),但离散化一下就好了。
剩下的就是判断不合法(无解)情况:
- \(b_i > c_i\),这个通过样例二就能看出来,并且 \(\min \{a_i, a_{i+1} \} > \max \{a_i, a_{i+1} \}\) 这本来就是不合法的。
- 还有就是 \(b,c\) 序列没有构成欧拉路径,这个可以根据度数为奇数的点的数量来判断,只有 \(0\) 和 \(2\) 的情况是合法的。
- 当然图可能不连通,所以我们只
dfs
一遍,如果栈中的元素不等于 \(n\),也是无解的。
这里建议用 vector
存边,并且用数组 \(now\) 来记录当前点遍历到了那条边,下次经过的时候可以跳过前面已经遍历过的边,达到优化复杂度的效果,以防被卡到 \(O(m^2)\)。
注意一对 \(b_i,c_i\) 所连的边是双向边,vector
本身是不方便同时对一对边标记的,不过我们可以对每条边多存一个信息 \(id\) (表示它是第几条边)来解决。
Code
/*
Work by: Suzt_ilymics
Problem: 不知名屑题
Knowledge: 垃圾算法
Time: O(能过)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
#define orz cout<<"lkp AK IOI!"<<endl
using namespace std;
const int MAXN = 3e5+5;
const int INF = 1e9+7;
const int mod = 1e9+7;
struct node {
int v, id;
};
int n;
int b[MAXN], c[MAXN];
int date[MAXN], date_num = 0, Cnt = 0;
vector<node> e[MAXN];
int now[MAXN], du[MAXN];
int stc[MAXN], sc = 0;
bool vis[MAXN];
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
return f ? -s : s;
}
void dfs(int u) {
for(int M = e[u].size(); now[u] < M; ) {
node v = e[u][now[u]++];
if(vis[v.id]) continue;
vis[v.id] = true;
dfs(v.v);
}
stc[++sc] = u;
}
int main()
{
n = read();
for(int i = 1; i < n; ++i) date[++date_num] = b[i] = read();
for(int i = 1; i < n; ++i) date[++date_num] = c[i] = read();
for(int i = 1; i < n; ++i) {
if(b[i] > c[i]) {
puts("-1");
return 0;
}
}
sort(date + 1, date + date_num + 1), date[0] = -INF;
for(int i = 1; i <= date_num; ++i) if(date[i] != date[i - 1]) date[++Cnt] = date[i];
for(int i = 1; i < n; ++i) {
b[i] = lower_bound(date + 1, date + Cnt + 1, b[i]) - date;
c[i] = lower_bound(date + 1, date + Cnt + 1, c[i]) - date;
e[b[i]].push_back((node){c[i],i}), du[c[i]]++;
e[c[i]].push_back((node){b[i],i}), du[b[i]]++;
}
int js = 0;
for(int i = 1; i <= Cnt; ++i) if(du[i]&1) js++;
if(js != 0 && js != 2) {
puts("-1");
return 0;
}
bool flag = false;
for(int i = 1; i <= Cnt; ++i) {
if(du[i] & 1) {
dfs(i);
flag = true;
break;
}
}
if(!flag) dfs(1);
if(sc != n) puts("-1");
else while(sc) printf("%d ", date[stc[sc--]]);
return 0;
}