题目大意:
给定一些大写字母之间的关系,去判断能否唯一确定他们之间的关系,也就是按照大小排列的序列,或者所给的关系中有相互矛盾的部分,或者不能判断他们之间的唯一关系(即按照所给信息,可能的关系不唯一)。
题目分析:
此题和士兵排队类似,是典型的拓扑排序(topsort)来实现。
Topsort:1.可以利用栈来解决,每次入栈的是入度为0的节点。
2.拓扑排序的答案:①可以判断。②出现了矛盾(有环)③条件不足无法判断。
(鉴于judge有些略坑)对于答案的输出,当 前两种出现时,直接输出,当前两种都不出现时,输出第三种。
有关代码简介:(1):对于可以确定关系的,必须满足在建立的图中,有且只有一个入度为零的点,但允许子图有多个无前驱的点。
(2):一旦形成环,则证明所给关系中有矛盾的。
(3):在全部输入完成,且前两种情况都尚未发生时,我们进行判断。
1、图中字母是全的,但是有多个无前驱的点。
2、图中字母残缺。
如下代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<stack>
#define N 27
using namespace std;
int n,m;
int graph[N][N],indegree[N],list[N];
int topsort(int n)
{
int in[N];
memcpy(in,indegree,sizeof(indegree));
stack<int> s;//我们可以利用栈来维护
int i;
for(int i=0;i<n;i++)
if(!in[i])//入度为零加入栈
s.push(i);
bool flag=false;
int t,j=0;
while(!s.empty())
{
if(s.size()>1)
flag=true;
t=s.top();
s.pop();
list[j++]=t;//记录
for(int i=0;i<n;i++)
if(graph[t][i])
if(--in[i]==0)//入度为1
s.push(i);
}
if(j!=n)
return 1;
else if(flag==true)
return 2;
return 0;
}
int main()
{
int deter,incon;
int i,j;
char a,b;
while(scanf("%d%d",&n,&m)&&n&&m)
{
getchar();
deter=0,incon=0;
memset(graph,0,sizeof(graph));
memset(indegree,0,sizeof(indegree));
for(int i=1;i<=m;i++)
{
scanf("%c<%c",&a,&b);
getchar();
if(!deter&&!incon)
{
if(graph[b-'A'][a-'A']==1)
{
incon=1;
printf("Inconsistency found after %d relations.\n",i);
continue;
}
if(graph[a-'A'][b-'A']==0)
{
graph[a-'A'][b-'A']=1;
indegree[b-'A']++;
}
int res=topsort(n);
if(res==0)
{
printf("Sorted sequence determined after %d relations: ",i);
for(int j=0;j<n;j++)
printf("%c",list[j]+'A');
printf(".\n");
deter=1;
}
else if(res==1)
{
printf("Inconsistency found after %d relations.\n",i);
incon=1;
}
}
}
if(!deter&&!incon)
printf("Sorted sequence cannot be determined.\n");
}
//while(1);
return 0;
}