洛谷P1155 雙棧排序題解(圖論模型轉換+二分圖染色+棧)
阿新 • • 發佈:2018-10-31
洛谷P1155 雙棧排序題解(圖論模型轉換+二分圖染色+棧)
標籤:題解
閱讀體驗:https://zybuluo.com/Junlier/note/1311990
原題地址:洛谷P1155 雙棧排序
那麼講題了
很好的一道圖論模型轉化的題目
考慮什麼情況下兩個元素一定要放在不同的棧內
經過一番仔細思考+草稿模擬你會得出
當且僅當存在三元組\((i,j,k)\),其中\(i<j<k\)且\(v[k]<v[i]<v[j]\)時,\(i\)和\(j\)一定要放在兩個不同的棧內
抽象理解一下,如果\(i,j\)放在同一個棧內,後面還有一個比\(v[i],v[j]\)都小的\(v[k]\)
那麼根據這個建出一個圖(轉化模型)
當存在上面的情況時,在\((i,j)\)間連一條邊,表示\(i,j\)要在不同的棧內
就可以跑二分圖染色判斷合法性了,然後染完色根據題目模擬即可
題目還是很好的,多掌握一點題型就少一點措手不及
#include<bits/stdc++.h> #define il inline #define rg register #define ldb double #define lst long long #define rgt register int #define N 1050 #define M 1000050 #define qw ljl[i].to using namespace std; const int Inf=1e9; il int MAX(rgt x,rgt y){return x>y?x:y;} il int MIN(rgt x,rgt y){return x<y?x:y;} il int read() { int s=0,m=0;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();} while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar(); return m?-s:s; } int n; int v[N],Min[N]; stack<int> st1,st2; int hd[N],vis[N],col[N],cnt; struct EDGE{int to,nxt;}ljl[M<<1]; il void Add(rgt p,rgt q){ljl[++cnt]=(EDGE){q,hd[p]},hd[p]=cnt;} void Dfs(rgt now,rgt C) { vis[now]=1,col[now]=C; for(rgt i=hd[now];i;i=ljl[i].nxt) { if(vis[qw]) { if(col[qw]==C)puts("0"),exit(0); continue; }Dfs(qw,C^1); } } int main() { n=read(),Min[n+1]=Inf; for(rgt i=1;i<=n;++i)v[i]=read(); for(rgt i=n;i>=1;--i)Min[i]=MIN(Min[i+1],v[i]); for(rgt i=1;i<n;++i) for(rgt j=i+1;j<=n;++j) if(v[i]<v[j]&&Min[j+1]<v[i]) Add(i,j),Add(j,i); for(rgt i=1;i<=n;++i)if(!vis[i])Dfs(i,0); rgt wnt=1; for(rgt i=1;i<=n;++i) { if(col[i])st2.push(v[i]),printf("c "); else st1.push(v[i]),printf("a "); while((!st1.empty()&&st1.top()==wnt)||(!st2.empty()&&st2.top()==wnt)) { if(!st1.empty()&&st1.top()==wnt)st1.pop(),printf("b "); else st2.pop(),printf("d ");++wnt; } }return puts(""),0; }