POJ 1094 Sort it all out (Topsort)

题目大意:

给定一些大写字母之间的关系,去判断能否唯一确定他们之间的关系,也就是按照大小排列的序列,或者所给的关系中有相互矛盾的部分,或者不能判断他们之间的唯一关系(即按照所给信息,可能的关系不唯一)。

题目分析:

此题和士兵排队类似,是典型的拓扑排序(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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值