P1155 双栈排序

本来以为是一道排序题,然而看了一眼标签

woc,图论题,一脸懵逼~~~~~~

 

题意:给你两个栈,四种操作

操作 a

如果输入序列不为空,将第一个元素压入栈 $S_1$

操作 b

如果栈$S_1$不为空,将$S_1$ 栈顶元素弹出至输出序列

操作 c

如果输入序列不为空,将第一个元素压入栈$S_2$

操作 d

如果栈 $S_2$ 不为空,将$S_2$ 栈顶元素弹出至输出序列

然后,给你1-n的一个全排列,问能否双栈排序

能:输出字典序最小的操作序列,否则输出0

 

正解:二分图染色 --------------------by@ Harry·Shaun·Wang(lg)

1.首先考虑一个简单情况:单栈排序:

若存在一个k,使得i<j<k且a[k]<a[i]<a[j],则a[i]和a[j]不能压入一个栈中

用f[i]维护后缀最小值

状态:f[i]=min(a[i],a[i+1], ... ,a[n])

边界条件:f[n+1]=INF;

状态转移方程:f[i]=min(f[i+1],a[i]);

于是上述判断就转化为了f[j+1]<a[i] && a[i]<a[j]

把时间复杂度从$O(n^3)$优化到了$O(O^2)$

2.扩展到双栈排序:

如果a[i]和a[j]不能在一个栈内,即连接一条i与j之间的无向边,接下来我们只需要判断这个图是否为二分图

由于题目中说编号的字典序要尽可能的小,那么就把编号小的尽可能放到stack1

判断二分图的方法可以采用黑白染色的方式,先从编号小的开始染,第一个顶点染成黑色,相邻的顶点染成不同的颜色,如果发现黑白冲突,那么说明这个图不是一个二分图,是不合法的,输出0.

(DFS或BFS染色均可)

3.染色后所有黑色的点进stack1,所有白色的点进stack2,最后模拟输出过程就可以了.

 

详见代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define olinr return
#define love_nmr 0
#define _ 0
int f[1050];
int xl[1050];
int n;
int col[1050];
vector<int> G[1050];
queue<int> q;
struct node
{
    int st[1050];
    int tp;
    node()
    {
        memset(st,0,sizeof st);
        tp=0;
    }
    void pop()
    {
        tp--;
    }
    void push(int x)
    {
        tp++;
        st[tp]=x;
    }
    bool empty()
    {
        return tp==0;
    }
    int top()
    {
        return st[tp];
    }
};
node A;
node B;
/*----------------------------olinr love nmr---------------------------------------*/
inline void bfs(int now)
{
    while(!q.empty()) q.pop();
    q.push(now);
    col[now]=1;
    while(!q.empty())
    {
        int tp=q.front();
        q.pop();
        int siz=G[tp].size();
        for(int i=0;i<siz;i++)
        {
            int go=G[tp][i];
            if(col[go]==-1) 
            {
                col[go]=col[tp]^1;
                q.push(go);
            }
            else if(!(col[go]^col[tp]))
            {
                cout<<0;
                exit(0);
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    f[n+1]=0x7fffffff;
    for(int i=1;i<=n;i++)
        cin>>xl[i];
    for(int i=n;i>=1;i--)
        f[i]=min(f[i+1],xl[i]);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(xl[i]>f[j+1]&&xl[i]<xl[j])
            {
                G[i].push_back(j);
                G[j].push_back(i);
            }
        }
    memset(col,-1,sizeof col);
    for(int i=1;i<=n;i++)
        if(col[i]==-1)
            bfs(i);
    int tot=1;
    for(int i=1;i<=n;i++)
    {
        if(col[i]==1)
        {
            cout<<"a ";
            A.push(xl[i]);
        }
        else
        {
            cout<<"c ";
            B.push(xl[i]);
        }
        while((!A.empty()&&A.top()==tot)||(!B.empty()&&B.top()==tot))
        {
            if((!A.empty()&&A.top()==tot))
            {
                A.pop();
                cout<<"b ";
            }
            else
            {
                B.pop();
                cout<<"d ";
            }
            tot++;
        }
    }
    olinr ~~(0^_^0)+love_nmr;
}

 

posted @ 2018-08-16 10:28  olinr  阅读(233)  评论(0编辑  收藏  举报