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;
}
posted @ 2021-09-04 22:20  Suzt_ilymtics  阅读(60)  评论(0编辑  收藏  举报