字母排序问题

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1806

字母排序问题

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

G教授是XOI的负责人,有一天他竟然发现自己的计算机染上了一种不常见的病毒。这种病毒的名字叫做ALPHABETVIRUS,当它发作的时候,会将字母用其他的字母代替,但不会将单词的顺序交换。

病毒将计算机中的所有文档都作了相对应的改变。很幸运,G教授的计算机上有一个字典,而我们都知道字典单词是按字母顺序排列的,当然,这个字典也被病毒改变了。因此,要利用字典原来的有序性,找到病毒替换字母的规律,再用以恢复其他文档。由于XOI不能缺少G教授的文件,所以文档必须恢复。但是由于G教授有其他更重要的工作完成,所以他希望你可以帮助他恢复文档,使得XOI的工作可以继续。

G教授会提供感染病毒后的字典和他希望你帮助恢复的字母组。

输入

第一行是两个整数A(<=26)和K(<=50000),A表示需要恢复的字母个数,K表示字典里与这几个字母有关系的单词个数,他们之间用一个空格隔开。接下的K行按原来的字典顺序给出这K个单词。第K+1行是要你恢复的字母组,字母为小写字母。

输出

将字母组输出,如果不可将字母区分,则输出0。

示例输入

5 6
cebdbac
cac
ecd
dca
aba
bac
cedab

示例输出

abcde
分析:首先统计题目中出现的字母,如果与n相同则继续;否则结束;然后对输入的单词,每相邻的两个进行比较,建立单向图,然后拓扑排序,如果不能完成拓扑排序或者拓扑排序的结果不是唯一的则输出0,否则输出对应的正确单词:
程序:
#include"stdio.h"
#include"string.h"
#define M 50050
#define inf 1000000000
char ch[M][100],str[2222];
int in[33],use[33];
int main()
{
    int G[33][33];
    int n,m,i,j,k;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(i=1;i<=m;i++)
            scanf("%s",ch[i]);
        scanf("%s",str);
        memset(G,0,sizeof(G));
        memset(in,0,sizeof(in));
        memset(use,0,sizeof(use));
        for(i=2;i<=m;i++)
        {
            int L1=strlen(ch[i-1]);
            int L2=strlen(ch[i]);
            int L;
            if(L1<L2)
                L=L1;
            else
                L=L2;
            for(j=0;j<L;j++)
            {
                if(ch[i][j]==ch[i-1][j])continue;
                int a=ch[i-1][j]-'a';
                int b=ch[i][j]-'a';
                G[a][b]=1;
                use[a]=use[b]=1;
                in[b]++;
                break;
            }
        }
        int sum=0;
        for(i=0;i<8;i++)
            if(use[i])
            sum++;
        if(sum!=n)
        {
            printf("0\n");
            continue;
        }
        int cnt=0;
        int s[33];
        for(k=1;k<=n;k++)
        {
            int flag=0;
            for(i=0;i<26;i++)
            {
                if(use[i]&&in[i]==0)
                {
                    flag++;
                }
            }
            //printf("::%d\n",flag);
            if(flag>=2||flag==0)
                break;
            for(i=0;i<26;i++)
            {
                if(!use[i])continue;
                if(in[i]==0)
                {
                    in[i]--;
                    s[cnt]=i;
                    cnt++;
                    for(j=0;j<=26;j++)
                    {
                        if(G[i][j]&&use[j])
                        {
                            in[j]--;
                        }
                    }
                    break;
                }
            }
        }
        //printf("%d \n",cnt);
        if(cnt!=n)
        {
            printf("0\n");
            continue;
        }
        int j=0;
        int ans[33];
        for(i=0;i<26;i++)
        {
            if(use[i])
            {
                ans[s[j++]]=i;
            }
        }
        for(i=0;str[i]!='\0';i++)
        {
            printf("%c",ans[str[i]-'a']+'a');
        }
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(排序)