题意:给出n个string 每个长度为l,n,l<=1e2.求确定字母的字典序使得n个string为从小到大排列,求出合法的字典序方案?
si和si+1第一个不相等的为u,v.若u!=v 则令边为u->v 表示字母v大于字母u
建好图之后,拓扑排序判环,如果图中无环,最后按照拓扑序输出方案即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+20;
vector<int> e[N];
vector<char> ans;
string s[N];
int ind[30],vis[30];
bool flag;
void Topo()
{
priority_queue<int,vector<int>,greater<int> > q;//小..大
for(int i=0;i<26;i++)
{
if(ind[i]==0)
q.push(i);
}
while(!q.empty())
{
int k=q.top();
ans.push_back(k+'a');
q.pop();
for(int i=0;i<e[k].size();i++)
{
int v=e[k][i];
ind[v]--;
if(ind[v]==0)
q.push(v);
}
}
if(ans.size()==26)
flag=true;
else//还有点 则存在环
flag=false;
}
int main()
{
int n;
while(cin>>n)
{
flag=true;
memset(ind,0,sizeof(ind));
for(int i=0;i<30;i++)
e[i].clear();
for(int i=0;i<n;i++)
cin>>s[i];
for(int i=0;i<n-1;i++)
{
int j=i+1;
bool mk=true;
if(s[i].length()>s[j].length())
mk=false;
for(int k=0;s[i][k]&&s[j][k];k++)
{
int u=s[i][k]-'a';
int v=s[j][k]-'a';
if(u!=v)
{
e[u].push_back(v);
ind[v]++;
mk=true;
break;
}
}
if(mk==false)
flag=false;// sj为si的前缀 sj长度小
}
if(flag)
Topo();
if(flag)
{
for(int i=0;i<ans.size();i++)
cout<<ans[i];
cout<<endl;
ans.clear();
}
else
puts("Impossible");
}
return 0;
}