字母排序问题
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB
描述
G教授是xoi的负责人,有一天他竟然发现自己的计算机染上了一种不常见的病毒。这种病毒的名字叫做ALPHABETVIRUS,当它发作时,会将字母用其它的字母代替,但不会将顺序交换。
病毒将计算机中的所有文档都作了相对应的改变。很幸运,G教授的计算机上有一个字典,而我们都知道字典单词是按字母顺序排列的,当然,这个字典也被病毒改变了。因此,利用字典原来的有序性,找到自动替换字母的规律,再用以恢复其它文档。由于XOI不能缺少G教授的文件,所以文档必须恢复。但是由于G教授有其它更重要的工作要完成,所以他希望你可以帮助他恢复文档,使得XOI的工作可以继续。
G教授会提供感染病毒后的字典和他希望能帮助恢复的字典足。
输入
输入文件的第一行是两个整数A(A<=26)和K(K<=50000),A表示需要恢复的字母的个数,K表示字典里与这几个字母有关系的单词个数,它们之间用一个空格隔开。接下来的K行按原来的字典顺序给出这K个单词。第K+1行是要你恢复的字母组,字母为小写字母。
输出
输出文件应该将字母组输出,如果不可将字母区分,则输出0。
样例输入
5 6
cebdbac
cac
ecd
dca
aba
bac
cedab
样例输出
abcde
using namespace std;
int mp[27][27];
int mmp[27];
int cor[27];
int top=1;
int main()
{
int A,K;
scanf("%d%d",&A,&K);
string S1,S2,S3;
if(K<=1)
{
cout<<"0";
return 0;
}
cin>>S1;
int tot=K-1;
int n=K;
K--;
while(K--)
{
cin>>S2;
int l1=S1.length();
int l2=S2.length();
for(int i=0;i<min(l1,l2);i++)
{
int flag=0;
if(S1[i]!=S2[i])
{
mp[S1[i]-'a'+1][S2[i]-'a'+1]=1;
flag=1;
break;
}
}
S1=S2;
}
/*for(int i=1;i<=A;i++)
{
for(int j=1;j<=A;j++)
cout<<mp[i][j]<<"^";
cout<<endl;
}*/
for(int i=1;i<=A;i++)
for(int j=1;j<=A;j++)
mmp[j]+=mp[i][j];
while(tot--)
{
int flag=0,ans;
for(int i=1;i<=A;i++)
{
if(flag==2)
{
cout<<"0";
return 0;
}
if(mmp[i]==0)
{
ans=i;
mmp[i]=-1;
flag++;
cor[i]=top;
top++;
}
}
for(int j=1;j<=A;j++)
{
mmp[j]-=mp[ans][j];
}
//for(int i=1;i<=A;i++)
//printf("%d ",mmp[i]);
//printf("\n");
if(flag==0)
{
cout<<"0";
return 0;
}
}
/*for(int i=1;i<=top;i++)
cout<<char(cor[i]+'a'-1);*/
cin>>S3;
int l3=S3.length();
for(int i=0;i<l3;i++)
{
cout<<char(cor[S3[i]-'a'+1]+'a'-1);
}
}
、车站分级(level.cpp/c/pas)——拓扑排序
描述
一条单向的铁路线上,依次有编号为1,2,...,n的n个火车站。每个火车站都有一个级别,最低为1级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站x,则始发站、终点站之间所有级别大于等于火车站x的都必须停靠。
(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是5趟车次的运行情况。其中,前4趟车次均满足要求,而第5趟车次由于停靠了3号火车站(2级)却未停靠途经的6号火车站(亦为2级)而不满足要求。
现有m趟车次的运行情况(全部满足要求),试推算这n个火车站至少分为几个不同的
级别。
【输入】
输入文件为level.in。
第一行包含2个正整数n,m,用一个空格隔开。
第i+1行(1≤i≤m)中,首先是一个正整数si(2≤si≤n),表示第i趟车次有si个停
靠站;接下来有si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个
空格隔开。输入保证所有的车次都满足要求。
【输出】
输出文件为level.out。
输出只有一行,包含一个正整数,即n个火车站最少划分的级别数。
【输入输出样例】
level.in | level.out |
92 41356 3356 | 2 |
93 41356 3356 3159 | 3 |
【数据范围】
对于20%的数据,1≤n,m≤10;
对于50%的数据,1≤n,m≤100;
对于100%的数据,1≤n,m≤1000。
#include<bits/stdc++.h>
using namespace std;
#define N 1001
struct edge
{
intv,next,to;
}mem[N*N];
int n,m,size,MAX;
int a[N],head[N],in[N],q[N],ans[N];
bool mapp[N][N],v[N];
void add(int from,int to)
{
size++;
mem[size].to=to;
mem[size].next=head[from];
head[from]=size;
}
void topsort()
{
int tot=0;
int tmp=1;
for(inti=1;i<=n;i++)
if(in[i]==0){//计算入度为零的点
tot++;
q[tot]=i;
}
while(tot<n){
intkobe=0;//Kobe记录的是这一次有几个新进入队列的点 没错就是Kobe Bryant
for(inti=tmp;i<=tot;i++){//小优化 上一波处理完毕的这一次不管了
intnow=q[i];
for(inte=head[now];e;e=mem[e].next){
in[mem[e].to]--;
if(in[mem[e].to]==0){
kobe++;
q[tot+kobe]=mem[e].to;//起点加上kobe为序号
ans[mem[e].to]=ans[now]+1;//转移
}
}
}
tmp=tot+1;//指针改变
tot=tot+kobe;
}
}
int main()
{
freopen("level.in","r",stdin);
freopen("level.ans","w",stdout);
scanf("%d%d",&n,&m);
for(inti=1;i<=m;i++){
int si;
memset(v,0,sizeof(v));
scanf("%d",&si);
for(intj=1;j<=si;j++){
scanf("%d",&a[j]);
v[a[j]]=1;//记录是否停过
}
for(intj=a[1];j<=a[si];j++){//枚举从起点到终点的点
if(v[j])continue;//停过跳过
for(intk=1;k<=si;k++) //枚举停过的点
if(mapp[a[k]][j]==0)add(a[k],j),mapp[a[k]][j]=1,in[j]++;
}
}
topsort();
for(inti=1;i<=n;i++)MAX=max(MAX,ans[i]);
printf("%d",MAX+1);//别忘了ans没有赋初值 最大的等级也是一个 要都加1
}