题目链接在这里:ACM UVa #200 - Rare Order
本题的解法相对简单:
对于输入的所有字符串,只需两两比较,每个字符串可以获得一个不等关系(或者无法获得),如:
ZXY
ZXW
可以知道Y < W
按照此种方法依次两两比较,可以获得多个不等关系。
当有了不等关系之后,下一步是如何根据不等关系得到这些字符的Order。最有效的方法是拓扑排序(Topology Sort):首先对于每个不等关系,构造出图的一条边,比如Y < W可以构造出一条边,从W到Y。这样,当整个图构造完毕的时候,出度为0的就是最小的字母,然后去掉这个字母的结点及上面的所有边,再次获得出度为0的字母,这将是第二小的字母,依此类推可以获得所有字母的顺序。
这道题有两个地方需要注意:
- 有可能输入只有单个由单个字母组成的字符串,根据定义这种情况下也是合法的,如AAAAA,结果为A。这种情况需要加以特殊处理。
- 在构造不等关系的时候可能会遇到重复的不等关系,这个时候需要跳过,避免重复处理。(我就因为这个郁闷了好半天,一直WA)
代码如下:
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
<
string
.h
>

#define
MAX30

void
compare_str(
const
char
*
a,
const
char
*
b,
int
adj[MAX][MAX],
int
degree[MAX],
int
out_degree[MAX])
...
{
while(*a&&*b&&*a==*b)
...{
a++;
b++;
}
if(*a&&*b)
...{
//directedgraph
//a<----b(a<b)
intalpha_a=*a-'A';
intalpha_b=*b-'A';
if(adj[alpha_b][alpha_a]==0)
...{
adj[alpha_b][alpha_a]=1;
degree[alpha_a]++;
degree[alpha_b]++;
out_degree[alpha_b]++;
}
}
}

void
topo_print(
int
adj[MAX][MAX],
int
degree[MAX],
int
out_degree[MAX])
...
{
intalphabets[MAX];
intalphabets_max=0;
for(inti=0;i<MAX;++i)
...{
if(degree[i])
...{
alphabets[alphabets_max++]=i;
}
}
//printintopoorder
for(inti=0;i<alphabets_max;++i)
...{
intalpha=-1;
for(intj=0;j<alphabets_max;++j)
...{
intcurrent_alpha=alphabets[j];
if(out_degree[current_alpha]==0)
...{
alpha=current_alpha;
out_degree[current_alpha]=-1;
putchar(alpha+'A');
break;
}
}
//fixout_degree
for(intj=0;j<alphabets_max;++j)
...{
intcurrent_alpha=alphabets[j];
if(adj[current_alpha][alpha]>0)
...{
out_degree[current_alpha]--;
adj[current_alpha][alpha]=0;
}
}
}
}

int
main(
int
argc,
char
*
argv[])
...
{
intadj[MAX][MAX];
intout_degree[MAX];
intdegree[MAX];
intn=0;
memset(adj,0,sizeof(adj));
memset(out_degree,0,sizeof(out_degree));
memset(degree,0,sizeof(degree));
boolquit=false;
char*prev_str=newchar[255];
char*current_str=newchar[255];
scanf("%s",prev_str);
n++;
while(!quit)
...{
scanf("%s",current_str);
if(strcmp(current_str,"#")==0)
quit=true;
else
...{
n++;
compare_str(prev_str,current_str,adj,degree,out_degree);
//swapprev_str¤t_strandusenewcurrent_str
char*temp=prev_str;
prev_str=current_str;
current_str=temp;
}
}
if(n==1)
putchar(prev_str[0]);
else
topo_print(adj,degree,out_degree);
putchar(' ');

deleteprev_str;
deletecurrent_str;
return0;
}

137

被折叠的 条评论
为什么被折叠?



