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