一道例题:
对于给出的字母,确定大小关系
poj1094_toposort
题意:给你一些大写字母间的偏序关系,然后让你判断能否唯一确定它们之间的关系,或者所给关系是矛盾的,或者到最后也不能确定它们之间的关系。
分析:
用拓扑排序:
1.拓扑排序可以用栈来实现,每次入栈的是入度为0的节点。
1.拓扑排序的结果一般分为三种情况:1、可以判断 2、有环出现了矛盾 3、条件不足,不能判断.
2.这道题不仅需要判断这三种情况,而且还要判断在处理第几个关系时出现前两种情况,对于本道题来说三种情况是有优先级的。前两种情况是平等的谁先出现先输出谁的相应结果,对于第三种情况是在前两种情况下都没有的前提下输出相应结果的.
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
//toposort的三种情况
//188K 0MS
const int N=27;
int n,m;
int graph[N][N],indegree[N],list[N];
int toposort(int n)
{
int in[N];
memcpy(in,indegree,sizeof(indegree)); //复制入度数组,以免对主函数中的indegree有影响
stack<int> s;
int i;
for(i=0;i<n;i++)
if(!in[i])
s.push(i);//所有入度为0的点入栈,如果这些点多于1的话,序列不确定
int flag=0;
int t,j=0;
while(!s.empty())
{
if(s.size()>1)
flag=1; //序列不确定
t=s.top();
s.pop();
list[j++]=t; //记录出栈的数字
for(i=0;i<n;i++)
if(graph[t][i])
if(--in[i]==0)
s.push(i);//入度为0的点入栈
}
if(j!=n)//不能拓扑排序,即有环 // 这里j<n也可以AC 明白了,因为当有环出现时就没有入度为0的点了
return 1;
else if(flag==1)//有多种排序方式,不能唯一确定
return 2;
return 0;//序列能够被唯一确定
}
int main()
{
int determined,inconsistency;
int i,j,res;
char a,b;
while(scanf("%d%d",&n,&m) && n!=0 && m!=0)
{
getchar();
determined=0;
inconsistency=0;
memset(graph,0,sizeof(graph));
memset(indegree,0,sizeof(indegree));
for(i=1;i<=m;i++)
{
scanf("%c<%c",&a,&b);
getchar();
if(!determined && !inconsistency)
{
if(graph[b-'A'][a-'A']==1)//存在反向边,则发现矛盾
{
inconsistency=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']++;
}
res=toposort(n);//toposort
if(res==0)//序列能够被唯一确定
{
printf("Sorted sequence determined after %d relations: ",i);
for(j=0;j<n;j++)
printf("%c",list[j]+'A');
printf(".\n");
determined=1;
}
else if(res==1)//不能拓扑排序,即有环,发现矛盾
{
printf("Inconsistency found after %d relations.\n",i);
inconsistency=1;
}
}
}
if(!determined && !inconsistency)//既没有唯一确定,也没发现矛盾(有环),即不能确定
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}