今天校内考试,差10分就AK了QAQ。
T1图论题正解BFS双端队列优化,但听说SPFA的 O ( k ∗ m ) O(k*m) O(k∗m)到 O ( n ∗ m ) O(n*m) O(n∗m)能卡过,因为是随机数据。一念之差以为会被卡,就走上了Dijkstra的 O ( ( n + m ) l o g m ) O((n+m)logm) O((n+m)logm)的不归路……难受。
不过话说回来这次的T2也很有意思。正解是DFS但在下打挂了,写出来了但调不对,一气之下直接重构全排列暴力结果A掉,还跑得飞快。
这样就诞生了一个SAO操作。
题目
WOJ#4375 约束
WOJ题目链接
题目描述
给出 n 个互不相同的小写字母,表示出现的字符类型,以及k个约束关系:,表示 ai 必须出现在bi前面(ai,bi 不会超出所给字符类型的范围,且ai!=bi)。
请按照字典序输出所有满足约束条件的序列。
如:
n=3,字符类型为:x y z
k=1,约束条件为:x z,表示 x 必须出现在 z 的前面。
所有满足约束条件的排列有:
xyz
xzy
yxz
输入
第 1 行,2 个整数 n 和 k。
第 2 行,n 个空格隔开的字符。
接下来 k 行,每行二个字符 ai 和 bi(表示约束关系),数据保证不会出现矛盾的关系。
输出
若干行,每行 n 个字符(字符之间没有空格),表示排列的结果。
样例
- 输入样例
3 1
x y z
x z - 输出样例
xyz
xzy
yxz
说明
对于 100%的数据:1<n<9,1≤k≤8。
题意
给出 k k k个字符对并规定其出现顺序,求合法的排列方式,并用字典序输出。
思路
首先拿到了 n n n个字符,那么既然最后要字典序输出,就先排个序吧。
然后如果要打正解的话,就该考虑一下存储方式、遍历顺序,还有最关键的,就是检查的部分。
但像我这种打不来正解的蒟蒻,就可以看一下数据规模,然后考虑全排列,然后检查每种顺序的合法性。
具体操作,可以考虑将字符存在
c
[
]
c[ ]
c[]里,然后再用一个
m
a
p
<
c
h
a
r
,
i
n
t
>
map<char,int>
map<char,int>,以便用字符查找位置。然后关于第
i
i
i个字符,把必须放在它前面的字符存在
t
e
r
m
[
i
]
[
]
term[i][ ]
term[i][]内。在检查时,把当前字符
i
i
i的
v
i
s
vis
vis设为1,遍历一遍它的
t
e
r
m
term
term。如果出现没有被遍历过的
i
i
i前辈(误),即
v
i
s
vis
vis为0,就说明前辈一定在
i
i
i后面,即为非法。遇到这种情况就直接跳,否则输出答案。
至于全排列的方式……刚刚见了一个套了9个循环的同学。やれやれ,如果不是几个月前刷题时学了一个叫next_permutation的东西,可能今天就也会……一直调正解了。
代码
#include<iostream>
#include<cstdio>
#include<cctype>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
int n,k,cnt;
int order[10]={0,1,2,3,4,5,6,7,8,9},term[10][10];
bool vis[10];
char a,b,c[10],ans[10];
map<char,int> idx;
inline int read()
{
int x=0;bool f=0;char c=getchar();
while(!isdigit(c)) {f|=c=='-';c=getchar();}
while(isdigit(c)) {x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}//决定了!这就是博主今后的新款读优
bool check()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
int x=order[i];
for(int j=1;term[x][j];j++)
if(!vis[term[x][j]]) return 0;//当前字符的前辈必须被全部遍历过
vis[order[i]]=1;
}
return 1;
}
int main()
{
n=read(),k=read();
for(int i=1;i<=n;i++) cin>>c[i];
sort(c+1,c+n+1);
for(int i=1;i<=n;i++) idx[c[i]]=i;//用字符调用位置
for(int i=1;i<=k;i++)
{
cin>>a>>b;
int m=idx[b];
term[m][++term[m][0]]=idx[a];
}//把位置信息存储在第0列里
do
{
if(check())
{
for(int i=1;i<=n;i++) cout<<c[order[i]];
cout<<"\n";
}
}
while(next_permutation(order+1,order+n+1));//全排列
return 0;
}