1. 程式人生 > 其它 >LG 題解 CF1152E Neko and Flashback

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