【二分圖匹配】 雙棧排序
阿新 • • 發佈:2020-07-11
題意
通過兩個棧,4中操作,實現輸入序列升序排序
- \(操作a:如果輸入序列不為空,將第一個元素壓入棧S_{1}\)
- \(操作b:如果棧S_{1}不為空,將S_{1}棧頂元素彈出至輸出序列\)
- \(操作c:如果輸入序列不為空,將第一個元素壓入棧S_{2}\)
- \(操作d:如果棧S_{2}不為空,將S_{2}棧頂元素彈出至輸出序列\)
如果一個\(1\sim n\)的排列\(P\)可以通過一系列操作使得輸出序列為
\(1, 2,\sim,(n-1), n\),就稱P是一個”可雙棧排序排列”。
操作序列為\(<a,c,c,b,a,d,d,b>\)
另一個可行的序列為\(<a,c,c,b,a,d,d,b>\)
如果序列可雙棧排序,輸出字典序最小的操作
否則輸出數字\(0\)
資料範圍
\(1 \leq n \leq 1000\)
題解
Code
cpp
#include <bits/stdc++.h> using namespace std; const int N=1010; int n; int a[N]; int f[N]; int color[N]; bool g[N][N]; stack<int>stk1,stk2; bool dfs(int u,int c){ color[u]=c; for(int i=1;i<=n;i++){ if(g[u][i]){ if(color[i] == c) return 0; if(color[i] == -1 && !dfs(i,!c)) return 0; } } return 1; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin>>n; memset(g,0,sizeof g); for(int i=1;i<=n;i++) cin>>a[i]; f[n+1]=n+1; for(int i=n;i>=1;i--) f[i]=min(f[i+1],a[i]); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(a[i] < a[j] && f[j+1] < a[i]) g[i][j]=g[j][i]=1; memset(color,-1,sizeof color); for(int i=1;i<=n;i++) if(color[i]==-1 && !dfs(i,0)){ cout<<0<<endl; return 0; } int now = 1; for(int i = 1; i<=n;i++){ if(color[i]==0) { stk1.push(a[i]); cout<<'a'<<' '; } else { stk2.push(a[i]); cout<<'c'<<' '; } while(1){ if(stk1.size() && stk1.top()==now){ cout<<'b'<<' '; stk1.pop(); now++; } else if(stk2.size() && stk2.top()==now){ cout<<'d'<<' '; stk2.pop(); now++; } else break; } } cout<<endl; }