Codeforces 510C Fox And Names【拓扑排序】

解决一个有趣的问题,即如何根据给定的作者名字列表找出一种字母排序方式,使得这些名字能按照字典序排列,或者判断这样的排序是否可能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fox And Names
time limit per test
 2 seconds
memory limit per test
 256 megabytes
input
 standard input
output
 standard output

Fox Ciel is going to publish a paper on FOCS (Foxes Operated Computer Systems, pronounce: "Fox"). She heard a rumor: the authors list on the paper is always sorted in the lexicographical order.

After checking some examples, she found out that sometimes it wasn't true. On some papers authors' names weren't sorted inlexicographical order in normal sense. But it was always true that after some modification of the order of letters in alphabet, the order of authors becomes lexicographical!

She wants to know, if there exists an order of letters in Latin alphabet such that the names on the paper she is submitting are following in the lexicographical order. If so, you should find out any such order.

Lexicographical order is defined in following way. When we compare s and t, first we find the leftmost position with differing characters:si ≠ ti. If there is no such position (i. e. s is a prefix of t or vice versa) the shortest string is less. Otherwise, we compare characters siand ti according to their order in alphabet.

Input

The first line contains an integer n (1 ≤ n ≤ 100): number of names.

Each of the following n lines contain one string namei (1 ≤ |namei| ≤ 100), the i-th name. Each name contains only lowercase Latin letters. All names are different.

Output

If there exists such order of letters that the given names are sorted lexicographically, output any such order as a permutation of characters 'a'–'z' (i. e. first output the first letter of the modified alphabet, then the second, and so on).

Otherwise output a single word "Impossible" (without quotes).

Sample test(s)
input
3
rivest
shamir
adleman
output
bcdefghijklmnopqrsatuvwxyz
input
10
tourist
petr
wjmzbmr
yeputons
vepifanov
scottwu
oooooooooooooooo
subscriber
rowdark
tankengineer
output
Impossible
input
10
petr
egor
endagorion
feferivan
ilovetanyaromanova
kostka
dmitriyh
maratsnowbear
bredorjaguarturnik
cgyforever
output
aghjlnopefikdmbcqrstuvwxyz
input
7
car
care
careful
carefully
becarefuldontforgetsomething
otherwiseyouwillbehacked
goodluck
output
acbdefhijklmnogpqrstuvwxyz

题目大意:

给你n个按照字典序从小到大排序的几个单词,问你能否有一个字典序能够满足上诉条件。

e.g:

bb

ac两个单词,现在就表示字符a比字符b的字典序大了,问能否找到一个合理的字典序满足上述条件。


思路:


1、首先明确一点,是输出任意一个满足以上约束条件的一个解即可,也就是说有spj......................mdzz处理了半天将答案和自己的输出一致...........


2、不难想到,这是一道裸的拓扑排序的题目,我们按照字符串给出的顺序进行建边,后串中第一个和前串不同的字符建立有向边,建立一个拓扑排序的模型,然后将拓扑排序的结果跑出来,就是一个对于约束条件部分的一个可行解,对于没有约束条件的部分我们直接按照26个字母的顺序输出即可。


3、对于拓扑排序中有环的情况出现,需要输出Impossible(也就是有约束条件的那些字母不满足拓扑序)【判定条件:有约束条件的字母跑拓扑排序过程中记录达到ans【】的个数+没有约束条件的字母个数<26】。另外还有一个条件比较坑,对于给定的字符串中,如果前串比后串长,并且后串和前串有字母的位子一一对应,(比如前串是abcdeeeee,后串是abcd),显然给出的前串和后串不满足字典序从小到大这种条件,也要输出I没possible......(真的是没想到在输入的字符串里边还有违背字典序的情况出现)


具体详细部分参考代码;


Ac代码:


#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int next;
}e[151515];
int cont;
int vis[500];
int head[500];
char a[500][500];
int degree[500];
char ans[500];
char ans2[500];
void add(int from,int to)
{
    e[cont].to=to;
    e[cont].next=head[from];
    head[from]=cont++;
}
void Topsort()
{
    int tmp=0;
    int tmp2=0;
    queue<int >s;
    for(int i=1;i<=26;i++)
    {
        if(vis[i]==0)
        {
            ans[tmp++]=i-1+'a';
        }
    }
    for(int i=1;i<=26;i++)
    {
        if(vis[i]==1&°ree[i]==0)
        {
            s.push(i);
            degree[i]=-1;
        }
    }
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        ans2[tmp2++]=u-1+'a';
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            degree[e[i].to]--;
            if(degree[e[i].to]==0)
            {
                s.push(e[i].to);
                degree[e[i].to]=-1;
            }
        }
    }
    if(tmp+tmp2==26)
    {
        for(int i=0;i<tmp;i++)
        {
            printf("%c",ans[i]);
        }
        for(int i=tmp2-1;i>=0;i--)
        {
            printf("%c",ans2[i]);
        }
        printf("\n");
    }
    else printf("Impossible\n");
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        cont=0;
        int ok=1;
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        memset(degree,0,sizeof(degree));
        for(int i=0;i<n;i++)
        {
            scanf("%s",a[i]);
        }
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                int flag=1;
                int n1=strlen(a[i]);
                int n2=strlen(a[j]);
                for(int k=0;k<n1&&k<n2;k++)
                {
                    if(a[i][k]==a[j][k])continue;
                    else
                    {
                        vis[a[j][k]-'a'+1]=1;
                        vis[a[i][k]-'a'+1]=1;
                        add(a[j][k]-'a'+1,a[i][k]-'a'+1);
                        degree[a[i][k]-'a'+1]++;
                        flag=0;
                        break;
                    }
                }
                if(flag==1)
                {
                    if(n1>n2)ok=0;
                }
            }
        }
        if(ok==1)
        Topsort();
        else printf("Impossible\n");
    }
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值