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教授会提供感染病毒后的字典和他希望你帮助恢复的字母组。
病毒将计算机中的所有文档都作了相对应的改变。很幸运,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;
}