题目
题目大意
给你 n n n 个串,通过改变字符优先级按指定顺序排列
思路
拓扑排序,考试时写Wa了。
首先,我们要判断有包含关系的情况
然后,对于排序后两个串第一个不同处我们令
A
[
i
]
A[i]
A[i]向
B
[
i
]
B[i]
B[i] 连边表示
A
[
i
]
<
B
[
i
]
A[i] <B[i]
A[i]<B[i]
跑完我们依次给字符赋值就可以了
回顾拓扑排序写法:
将所有入度为0的点加入队列,每次取出一个节点记录并删除连接其他点的边,同时再加入入度为0的点,最后如果记录节点小于n则有环无解。
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return f*x;
}
#define MAXN 100
#define INF 0x3f3f3f3f
int in[MAXN+5];
vector<int> G[30];
char chan[MAXN+5];
void Topological_Sort(int n){
priority_queue<int,vector<int>,greater<int> > Q;
vector<int> Ans;
for(int i=1;i<=n;i++)
if(!in[i]) Q.push(i);
while(!Q.empty()){
int u=Q.top();Q.pop();
Ans.push_back(u);
for(int i=0;i<int(G[u].size());i++){
int v=G[u][i];
in[v]--;
if(!in[v]) Q.push(v);
}
}
if(int(Ans.size())!=n)
puts("NE");
else{
puts("DA");
for(int i=1;i<=n;i++)
chan[Ans[i-1]]=i+'a'-1;
printf("%s\n",chan+1);
}
return ;
}
int A[MAXN+5];
char S[MAXN+5][MAXN+5],T[MAXN+5][MAXN+5];
int main(){
//freopen("cezar.in","r",stdin);
//freopen("cezar.out","w",stdout);
int n=read();
for(int i=1;i<=n;i++)
scanf("%s",S[i]+1);
for(int i=1;i<=n;i++)
A[i]=read(),memcpy(T[i]+1,S[A[i]]+1,strlen(S[A[i]]+1));
for(int t=1;t<n;t++){
bool flag=0;
for(int i=1;i<=min(strlen(T[t]+1),strlen(T[t+1]+1));i++){
if(T[t][i]!=T[t+1][i]){
G[T[t][i]-'a'+1].push_back(T[t+1][i]-'a'+1);
in[T[t+1][i]-'a'+1]++;
flag=1;
break;
}
}
if(!flag&&strlen(T[t]+1)>strlen(T[t+1]+1)){
puts("NE");
return 0;
}
}
Topological_Sort(26);
return 0;
}