题意:给出n串名字,表示字典序从小到大,求符合这样的字符串排列的字典序
先挨个地遍历字符串,遇到不相同的时候,加边,记录相应的入度
然后就是bfs的过程,如果某一点没有被访问过,且入度为0,则把它加入队列中,并将它指向的节点的入度减去1
另外如果len[i]<len[i-1],说明第i个字符串是i-1个字符串的前缀,但是它还排在后面,这样肯定不存在符合的字典序,直接输出“Impossible”
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<algorithm> 11 using namespace std; 12 13 typedef long long LL; 14 const int INF = (1<<30)-1; 15 const int mod=1000000007; 16 const int maxn=100005; 17 18 int e[maxn],first[maxn],next[maxn],ans[maxn],len[maxn],vis[maxn],in[maxn]; 19 char s[105][105]; 20 int ecnt; 21 22 void addedges(int u,int v){ 23 e[ecnt]=v; 24 next[ecnt]=first[u]; 25 first[u]=ecnt; 26 in[v]++; 27 ecnt++; 28 } 29 30 int main(){ 31 32 // freopen("in.txt","r",stdin); 33 // freopen("out.txt","w",stdout); 34 int n; 35 cin>>n; 36 37 memset(first,-1,sizeof(first)); 38 for(int i=1;i<=n;i++){ 39 cin>>s[i]; 40 len[i]=strlen(s[i]); 41 } 42 43 44 int j; 45 ecnt=0; 46 for(int i=2;i<=n;i++){ 47 for(j=0;j<min(len[i],len[i-1]);j++){ 48 if(s[i-1][j]!=s[i][j]){ 49 addedges(s[i-1][j]-‘a‘,s[i][j]-‘a‘); 50 break; 51 } 52 } 53 if(len[i]<len[i-1]&&j==len[i]){ 54 printf("Impossible\n"); 55 return 0; 56 } 57 } 58 59 60 memset(vis,0,sizeof(vis)); 61 62 for(int i=1;i<=26;i++){ 63 int jj=26; 64 int j; 65 for( j=0;j<26;j++){ 66 if(!vis[j]&&in[j]==0){ 67 vis[j]=1; 68 ans[i]=j; 69 for(int k=first[j];k!=-1;k=next[k]){ 70 in[e[k]]--; 71 } 72 jj=j; 73 break; 74 } 75 } 76 if(jj==26){//jj的值没有发生改变,说明这 一点找不到符合的拓扑序 77 printf("Impossible\n"); 78 return 0; 79 } 80 } 81 82 for(int i=1;i<=26;i++) 83 printf("%c",ans[i]+‘a‘); 84 printf("\n"); 85 return 0; 86 }
时间: 2024-11-05 19:36:44