排序
解题思路
这题虽然是一道蓝题,但他的数据很小,所以,我们可以每输入一个关系就拓扑一次
我们可以把结果分为三种情况
1.根据前x个关系得到整体关系
这里我们可以用拓扑把度清零,记录每个字母都出现过
并且判断最长的链是多少就行了
即f[a[i].to]=max(f[a[i].to],f[p[h]]+1);//找最长链 s=max(s,f[a[i].to]);
如果最长链小于n,那么就没有得到整体关系
提问
那么就有人问了,为什么得不到呢,难道不是经过拓扑后都为0,并且n个字母都出现过就行了吗?
回答
我们拿个样例来讲
4 6
C<D
C<B
B<A
C<D
D<A
A<A
按照预处理,形成一个这样的DAG(有向无环图)
1.C→D
2.C→D
↘
B
3.C→D
↘
B→A
当我们执行到第三步时,所有字母都出现过,并且经过拓扑排序,所有度都会为0,
但是答案却错了,因为D与B之间没有大小关系,最长链为C<B<A,长度<n
所以,要判断最长链是否等于n
接下来,就是输出的问题了
我们可以建邻接表,最小的为根,最大的为叶
这样,最先出队(也就是度为0)的字母就是最小的字母
if(s==n)//判断最长链是否为n,第一种情况
{
cout<<"Sorted sequence determined after "<<i<<" relations: ";
for(int j=1;j<=t;j++)cout<<char(p[j]+65);//按出队顺序输出
cout<<".";
return 0;
}
2.根据前x个关系即发现存在矛盾
这里,处理就很简单了,只要判断拓扑排序后,度是否还是大于0,实际就是判断有没有出现环
ok=1;
for(int j=0;j<n;j++)//判断是否有环
if(b[j]>0){
ok=0;break;}
3.根据这m个关系无法确定这n个元素的顺序
这里就更简单,如果1和2都没有成立,那么就是第3个条件
注意
还要有个特判
那刚刚的样例讲
4 6
C<D
C<B
B<A
C<D
D<A
A<A
最后一个是不是A<A,出现了矛盾
所以要输出
Inconsistency found after 6 relations.
所以要判断输入的两个字母是否相等
if(x==y)//特判
{
cout<<"Inconsistency found after "<<i<<" relations.";
return 0;
}
下面呈上AC代码
AC代码
#include<iostream>
using namespace std;
char ch;
int n,m,x,y,h,t,s,ok,tot,b[30],c[30],p[30],o[30],f[30],du[30],head[30];
struct node
{
int to,next;
}a[1005];
void add(int x,int y)//邻接表
{
a[++tot]=(node){
y,head[x]};
head[x]=tot;
}
void tp()//拓扑排序
{
h=t=s=0;//初值
for(int i=0;i<n;i++)//初值
{
o[i]=f[i]=0;
b[i]=du[i];
if(b[i]==0)p[++t]=i,o[i]=f[i]=1;//开始度为0就是根
}
while(h<t)
{
h++;
for(int i=head[p[h]];i;i=a[i].next)
if(o[a[i].to]==0)//如果a[i].to的度还没有为0,就循环
{
b[a[i].to]--;//度--
f[a[i].to]=max(f[a[i].to],f[p[h]]+1);//找最长链
s=max(s,f[a[i].to]);
if(b[a[i].to]==0)//度为0
{
p[++t]=a[i].to;//入队
o[a[i].to]=1;//标记
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>ch;//输入是字符
x=ch-65;
cin>>ch>>ch;
y=ch-65;
if(x==y)//特判
{
cout<<"Inconsistency found after "<<i<<" relations.";
return 0;
}
add(x,y);//建图
du[y]++;//度++
tp();//拓扑
ok=1;
for(int j=0;j<n;j++)//判断是否有环
if(b[j]>0){
ok=0;break;}
if(ok==0)//第2种情况
{
cout<<"Inconsistency found after "<<i<<" relations.";//注意有.
return 0;
}
if(s==n)//判断最长链是否为n,第1种情况
{
cout<<"Sorted sequence determined after "<<i<<" relations: ";
for(int j=1;j<=t;j++)cout<<char(p[j]+65);//按出队顺序输出
cout<<".";
return 0;
}
}
cout<<"Sorted sequence cannot be determined.";//如果前2种情况都不是,就是第3种
return 0;
}