别多说了,神题。
写不来,看得是大佬的题解
很妙,没想到用二分图染色,但是二分图染色的模型的确很适合这个题目。
不过关键还是那个判定定理。
题意:
给你一个序列,要你用两个栈给它排序,问你这个序列是否能排序成功。
思路:
上面的链接很详细,我这里简单说一蛤。
首先必须注意到判定两个数必须在两个不同的栈的充要条件。
S[i],S[j]两个元素不能进入同一个栈 <=> 存在k,满足i<j<k,使得S[k]<S[i]<S[j]. 证明略过,请参考sqybi.尝试后可以发现结论P是正确的.
我们首先用( O( n^2 ) ) 的复杂度预处理出必须在两个栈的位置,并对其连边,再对其染色,对没有限制的优先放在第一个栈中因为要字典序最小
通过染色判定,不能形成二分图则输出0,否则模拟输出序列。
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1005;
int ary[maxn];
int bmin[maxn];
int color[maxn];
int st1[maxn], st2[maxn], t1, t2;
vector<int> G[maxn];
bool dfs(int u, int c)
{
color[u] = c;
int sz = G[u].size(), v;
for (int i = 0; i < sz; i++) {
v = G[u][i];
if (!color[v] && !dfs(v, 3 - c))
return false;
else if (color[v] == c)
return false;
}
return true;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", ary + i);
bmin[n] = inf;
for (int i = n - 1; i >= 0; i--)
bmin[i] = min(bmin[i + 1], ary[i]);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (ary[i] < ary[j] && bmin[j + 1] < ary[i])
G[i].push_back(j), G[j].push_back(i);
for (int i = 0; i < n; i++)
if (!color[i] && !dfs(i, 1)) {
puts("0");
return 0;
}
int cur = 1;
for (int i = 0; i < n; i++) {
if (color[i] == 1) {
printf("a ");
st1[++t1] = ary[i];
} else {
printf("c ");
st2[++t2] = ary[i];
}
while (st1[t1] == cur || st2[t2] == cur) {
if (st1[t1] == cur)
printf("b "), t1--;
else
printf("d "), t2--;
cur++;
}
}
return 0;
}