【codevs1170】 双栈排序

http://codevs.cn/problem/1170/ (题目链接)

题意

  给出一个初始序列,判断能否通过两个栈的入栈和出栈操作构造出一个有序序列。若可以,输出字典序最小的方案。

Solution

  还是想狙LCF才看的这道题,真的是很神啊。考场绝对做不出的题之一。

  网上题解一大piang,那个结论其实很好YY出来,只是想不到转换到二分图染色上面去。。

代码

// codevs1170
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define MOD 100000000
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=1010;
struct edge {int to,next;}e[maxn<<1];
int c[maxn],head[maxn],a[maxn],f[maxn],s1[maxn],s2[maxn];
int t1,t2,n,cnt;

void link(int u,int v) {
	e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
	e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
}
bool color(int x,int cl) {
	c[x]=cl;
	for (int i=head[x];i;i=e[i].next) {
		if (!c[e[i].to]) {if (!color(e[i].to,3-cl)) return 0;}
		else if (c[e[i].to]==cl) return 0;
	}
	return 1;
}
int main() {
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	f[n+1]=inf;
	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] && f[j+1]<a[i]) link(i,j);
	for (int i=1;i<=n;i++)
		if (!c[i] && !color(i,1)) {puts("0");return 0;}
	int now=1;
	for (int i=1;i<=n;i++) {
		if (c[i]==1) printf("a "),s1[++t1]=a[i];
		else printf("c "),s2[++t2]=a[i];
		while (s1[t1]==now || s2[t2]==now) {
			if (s1[t1]==now) printf("b "),t1--;
			else printf("d "),t2--;
			now++;
		}
	}
	return 0;
}

  

posted @ 2016-10-04 16:43  MashiroSky  阅读(216)  评论(0编辑  收藏  举报