原题链接
题目大意
有 n ( 1 ≤ n ≤ 100 ) n(1\le n\le 100) n(1≤n≤100) 个单词,需要你设置一种字典序,让这些单词按照题目所给的顺序进行排序。
解题思路
比较好想的一种做法就是先建边,再进行拓扑排序。拓扑排序简单,只需要使用板子即可,但是建边就比较难了(调了一个上午!!!)。
如何建边?先看一个例子:
3
rivest
shamir
adleman
先从第一位建起:
3
r|ivest
s|hamir
a|dleman
为了让它们按照这个顺序排列,就要保证在字典序中: r < s < a r<s<a r<s<a,因为只要满足这个条件,就可以拍好序,所以,排完了。但是,如果出现开头相同:
3
r|ivest
s|hamir
s|dleman
这时,我们先通过开头一位可以确定 r < s r<s r<s 。但在确定最后两个单词时,就需要比较第二位:
3/*
r|ivest*/
s|h|amir
^
s|d|leman
^
接着我们就可以得到
h
<
d
h<d
h<d 。
最后还要注意两点:
- 当只有长度不同时(以防以下情况Impossible)
3
aaaaaaa
aaaa
a
- 每次要建多条边(以防以下情况没有Impossible)
5
ab
cb
db
ed
ea
代码实现
#include<iostream>
#include<map>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
int n,max_len,ans,N=1;
char px[110],q[110];
string s[110];
bool v[110];
map<char,vector<char> > e;
map<char,int> Map;
map<char,bool> ans_v,ans_v2;
void bfs()//拓扑排序(板子)
{
int t=0,h=0;
for(int i=0;i<26;i++)
if(!Map[char(i+'a')]){
q[++t]=char(i+'a');
px[++ans]=char(i+'a');
}
while(h<t){
h++;
char now=q[h];
for(int i=0;i<e[now].size();i++){
Map[e[now][i]]--;
if(!Map[e[now][i]]){
q[++t]=e[now][i];
px[++ans]=e[now][i];
}
}
}
}
void make_edge(int l,int r,int p)//建边
{
if(p>max_len-1)
return;
int l2=l,r2=l;
vector<char> now;
for(int i=l;i<r;i++){
if(s[i][p]==s[i+1][p])
r2=i+1;
else{
if(s[i][p]!=' ')
{
now.push_back(s[i][p]);
make_edge(l2,r2,p+1);//递归
}
l2=i+1;
}
}
if(s[r][p]!=' '){
now.push_back(s[r][p]);
make_edge(l2,r,p+1);
}
for(int i=0;i<now.size();i++){//每两点建一条边,枚举第一点
for(int j=i+1;j<now.size();j++){//每两点建一条边,枚举第二点
e[now[i]].push_back(now[j]);//建边
Map[now[j]]++;//累加入度
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
max_len=max(max_len,(int)s[i].size());
}
for(int i=1;i<n;i++){//特判长度
if(s[i].size()>s[i+1].size()&&s[i].substr(0,s[i+1].size())==s[i+1]){
cout<<"Impossible";
return 0;
}
}
for(int i=1;i<=n;i++){//统一长度
if(s[i].size()<max_len){
int len=s[i].size();
for(int j=1;j<=max_len-len;j++)
s[i]+=" ";
}
}
make_edge(1,n,0);
bfs();
if(ans!=26)
cout<<"Impossible";
else{
for(int i=1;i<=ans;i++)
cout<<px[i];
}
return 0;
}
样例1
输入
3
rivest
shamir
adleman
样例2(点13)
答案不唯一,可自行排序(非Impossible)
输入
20
jtjdxwguinrfqc
nayyakdmpf
dauemwdqilc
gerrqwvmqye
x
xgq
owixhphzh
ofcvwucgekbafr
aitdmozzauatr
eydxwjh
bmoexdnvbetb
fxtkzvf
frjdsldludgojnh
uqf
lmmrgyshzphefgifw
pajrijnnkor
viczzuevgcxpjxplwo
q
qtksab
cxovltrozgyisqhpityx
输出
答案不唯一,可自行排序(非Impossible)