题意:给出一组没有按字母表排序的英文名字,要求找出一种新的字母表顺序,使这组名字符合该字母表序。
解法:拓扑排序的应用,注意判断 xy 在 x 之前的情况。
// Codeforces 290C
#include<iostream>
#include<cstdio>
#include<cstring>
#include<memory.h>
using namespace std;
class alphaGraph{
private:
struct edgeNode{
char end;
edgeNode* next;
edgeNode(char e, edgeNode* n = NULL) : end(e), next(n) {}
edgeNode() : next(NULL) {}
};
struct verNode{
//char ch; // Need it?
edgeNode* head;
verNode() : head(NULL) {}
};
verNode table[26];
public:
char alphabet[30];
alphaGraph(){}
~alphaGraph(){
int i;
for (i = 0; i <= 25; i++){
edgeNode* tmp = table[i].head;
while (tmp){
table[i].head = table[i].head->next;
delete tmp;
tmp = table[i].head;
}
}
}
void insert(char s, char e){
table[s - 'a'].head = new edgeNode(e, table[s - 'a'].head);
}
bool exist(char s, char e){
edgeNode* tmp = table[s - 'a'].head;
while (tmp){
if (tmp->end == e) return true;
tmp = tmp->next;
}
return false;
}
bool checkLoop(){ // Apply the topological sort to find if loop exits
int i, cnt = 0, queue[100], front = 0, rear = 0, deg[26];
memset(deg, 0, sizeof(deg));
for (i = 0; i <= 25; i++) { // Calculate the degrees
edgeNode* tmp = table[i].head;
while (tmp){
deg[tmp->end - 'a']++;
tmp = tmp->next;
}
}
for (i = 0; i <= 25; i++)
if (deg[i] == 0) queue[rear++] = i;
// Dequeue the node with degree of 0, and calculate the degrees again in a loop
while (rear != front){
int cur = queue[front++];
alphabet[cnt++] = cur + 'a';
edgeNode* tmp = table[cur].head;
while (tmp){
deg[tmp->end - 'a']--;
if (deg[tmp->end - 'a'] == 0) queue[rear++] = tmp->end - 'a';
tmp = tmp->next;
}
}
if (cnt == 26) {
alphabet[26] = '\0';
return false;
}
else return true;
}
};
char name[110][110];
// Return true if there is a probable order
bool check(int st, int ed, int level, alphaGraph& gp){
int i;
for (i = st; i <= ed; i++){
// 找到下一个不相同的字符
while (i < ed && name[i + 1][level] == name[i][level]) i++;
if (i == ed) continue;
// x < xy
if (!name[i][level] && name[i + 1][level]) continue;
// xy < x
if (name[i][level] && !name[i + 1][level]) return false;
// 防止出现重边
if (!gp.exist(name[i][level], name[i + 1][level]))
gp.insert(name[i][level], name[i + 1][level]);
}
if (gp.checkLoop()) return false;
// 检查下一层
int next_ed;
for (i = st; i <= ed; i++){
if (name[i][level] == '\0') continue;
if (i < ed && name[i][level] == name[i + 1][level]){
next_ed = i;
while (next_ed < ed && name[next_ed][level] == name[next_ed + 1][level])
next_ed++;
if (!check(i, next_ed, level + 1, gp)) return false;
i = next_ed;
}
}
return true;
}
int main(){
int n, i;
cin >> n;
for (i = 0; i <= n - 1; i++) cin >> name[i];
alphaGraph gp;
if (check(0, n - 1, 0, gp)) cout << gp.alphabet << endl;
else cout << "Impossible" << endl;
return 0;
}