双栈排序

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int maxn=1007;
 5 const int INF=2147483647; 
 6 int a[maxn],imin[maxn],col[maxn],n,num;
 7 int stk1[maxn],stk2[maxn],top1,top2,head[maxn];
 8 struct Edge{
 9     int next,to;
10 }edge[maxn*maxn*10];
11 void add(int from,int to){
12     edge[++num].next=head[from];
13     edge[num].to=to;
14     head[from]=num;
15 }
16 bool dfs(int x){
17     for(int i=head[x];i;i=edge[i].next){
18         int v=edge[i].to;
19         if(!col[v]){
20             col[v]=col[x]^1;
21             if(!dfs(v)) return false;
22         }
23         else if(col[v]==col[x]) return false;
24     }
25     return true;
26 }
27 int main(){
28     cin>>n;
29     for(int i=1;i<=n;i++) cin>>a[i];imin[n+1]=INF;
30     for(int i=n;i>=1;i--) imin[i]=min(imin[i+1],a[i]); 
31     for(int i=1;i<=n;i++){
32         for(int j=i+1;j<=n;j++){
33             if(a[i]<a[j]&&a[i]>imin[j+1]){
34                 add(i,j);add(j,i);
35             }
36         }
37     }
38     for(int i=1;i<=n;i++){
39         if(!col[i]){
40             col[i]=2;
41             if(!dfs(i)) {cout<<0<<endl;return 0;}
42         }
43     }
44     int cnt=1;
45     for(int i=1;i<=n;i++){
46         if(col[i]==2) {stk1[++top1]=a[i];cout<<"a ";}
47         else {stk2[++top2]=a[i];cout<<"c ";}
48         while(top1&&stk1[top1]==cnt||top2&&stk2[top2]==cnt){
49             if(stk1[top1]==cnt){cout<<"b ";top1--;}
50             else {cout<<"d ";top2--;}
51             ++cnt;
52         }
53     }
54     return 0;
55 } 

 来自five20

本题二分图染色+栈模拟。  

  若我们知道每个数应该放在哪个栈中,就可以去模拟了。

  考虑数ai,aj,ak不能在同一栈的情况,若i<j<k,ai<aj,ai>aki<j<k,ai<aj,ai>ak那么i,ki,k是肯定不能在同一栈内的,我们对二元组建边,那么就是个二分图染色的模型了。

  由于要字典序最小,所以每次染色时另当前未被染色的位置为栈1再去dfs,染色后每个位置所在的栈就确定了。

  然后就是纯模拟咯。

  (安利一个神奇的调试技巧:用iostream库下的cerr代替cout,在评测机测试时会直接跳过这条输出语句,但在终端可以输出,这样就能防止忘记删调试语句而写挂!>.^_^.<)

posted @ 2018-09-09 21:59  lcan  阅读(211)  评论(0编辑  收藏  举报