首页 > 代码库 > 【codevs1170】 双栈排序

【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;}

  

【codevs1170】 双栈排序