LG 題解 CF1152E Neko and Flashback
阿新 • • 發佈:2021-09-05
當我把它公之於眾的那一刻,它原有的價值已經不存在了。
目錄
的兩個值,可以看做是兩個點連邊,而 \(b_{i+1}\) 和 \(c_{i+1}\) 又能將 \(a_{i+1}\) 和 \(a_{i+2}\) 連線。最後整個 \(a\) 序列就是一條由每一對 \(b_i,c_i\) 連起來的合法的尤拉路徑。
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,c\) 序列的值域是 \(10^9\),但離散化一下就好了。
剩下的就是判斷不合法(無解)情況:
- \(b_i > c_i\),這個通過樣例二就能看出來,並且 \(\min \{a_i, a_{i+1} \} > \max \{a_i, a_{i+1} \}\) 這本來就是不合法的。
- 還有就是 \(b,c\) 序列沒有構成尤拉路徑,這個可以根據度數為奇數的點的數量來判斷,只有 \(0\)
- 當然圖可能不連通,所以我們只
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; }