[洛谷P1155]双栈排序:二分图染色+模拟

分析:

发现如果i<j<k&&a[i]<a[j]&&a[i]>a[k],a[i]和a[j]就不能在一个栈中。
因为a[i]<a[j],所以a[j]不能去a[i]的栈里,并且a[i]不能弹出,因为a[k]还在。
这种关系可以用并查集维护,当然用二分图染色也可以。
若a[i],a[j]不能在一个栈,那在i和j间连一条边。
这张图如果是二分图,则有解。
输出解时直接模拟即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
int n,a[1005],f[1005],ecnt,head[1005],col[1005];
int stk1[1005],stk2[1005],top1,top2;
struct Edge{
    int to,nxt;
}e[1000005];
inline void add_edge(int bg,int ed){
    ecnt++;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    head[bg]=ecnt;
}
void dfs(int x,int c){
    col[x]=c;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(col[ver]==-1) dfs(ver,c^1);
        else if(col[ver]==(c^1)) continue;
        else{
            printf("0\n");
            exit(0);
        }
    }
}
int main(){
    memset(col,-1,sizeof col);
    scanf("%d",&n);f[n+1]=1e9;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=n;i;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]) continue;
            if(a[i]<=f[j+1]) continue;
            add_edge(i,j);add_edge(j,i);
        }
    for(int i=1;i<=n;i++)
        if(col[i]==-1) dfs(i,0);
    int now=0;
    for(int i=1;i<=n;i++){
        if(col[i]==0){
            stk1[++top1]=a[i];printf("a ");
        }
        else{
            stk2[++top2]=a[i];printf("c ");
        }
        while(stk1[top1]==now+1||stk2[top2]==now+1){
            if(stk1[top1]==now+1){
                top1--;printf("b ");
            }
            else{
                top2--;printf("d ");
            } 
            now++;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9573896.html
今日推荐