<题目链接>
题目大意:
给你一些只由小写字母组成的字符串,现在按一定顺序给出这些字符串,问你怎样从重排字典序,使得这些字符串按字典序排序后的顺序如题目所给的顺序相同。
解题分析:
本题想到拓扑排序就好做了。就是枚举每个字符串,每个字符串和它前一个字符串寻找第一个不同的字符,然后前一个串的该字符向当前串的字符连一条有向边(注意判断后一个串是前一个串的子串的情况)。然后就是跑一遍拓扑排序,如果不冲突的话,就可构造出答案。
#include <bits/stdc++.h> using namespace std; #define pb push_back string str[110]; vector<int>G[30]; int ind[30]; vector<int>ans; inline void TopoSort(){ queue<int>q; for(int i=0;i<26;i++){ if(!ind[i])q.push(i); } while(q.size()){ int u=q.front();q.pop(); ans.pb(u); ind[u]=-1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; //得到它的子节点 ind[v]--; if(ind[v]==0)q.push(v); } } } int main(){ int n;cin>>n; for(int i=1;i<=n;i++) cin>>str[i]; for(int i=2;i<=n;i++){ //枚举字符串 int len1=str[i-1].size(); int len2=str[i].size(); bool fp=false; for(int j=0;j<min(len1,len2);j++){ if(str[i-1][j]!=str[i][j]){ int u=str[i-1][j]-‘a‘; int v=str[i][j]-‘a‘; G[u].pb(v); ind[v]++; //记录这个点的入度 fp=true; break; }//找到第一个不同的元素 } if(!fp&&len1>len2)return puts("Impossible"),0; //如果当前串是前一个串的子串 } TopoSort(); if(ans.size()<26)puts("Impossible"); else { for(int i=0;i<ans.size();i++) printf("%c",ans[i]+‘a‘); puts(""); } }
CodeForces 510C Fox And Names (拓扑排序)
原文:https://www.cnblogs.com/00isok/p/10713131.html