poj1094 Sorting It All Out 【拓扑排序】

Description

An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

Input

Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

Output

For each problem instance, output consists of one line. This line should be one of the following three:

Sorted sequence determined after xxx relations: yyy...y.
Sorted sequence cannot be determined.
Inconsistency found after xxx relations.

where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy...y is the sorted, ascending sequence.

Sample Input

4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0

Sample Output

Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.

题意:输入n和m,再输入m条关系语句,根据关系语句判断是否能够组成没有回环的有序序列,如果能组成,则输出在读入第几条关系语句能够构成有序字母序列且输出有序字母序列,如果出现回环,则输出在读入第几条关系语句时能构成回环。

思路:拓扑排序的应用。题目上给定了序列的三种关系:1:无环有序:2:有环:3:无序。判断这三种关系的先后顺序为:先判断是否出现环,如果没有,则判断是否有序,如果无序,则是最后一种情况。

判断是否有环。如果序列无环,那么在经过拓扑排序后,入度为0的点肯定等于总点数n,否则说明有环。

判断是否有序。如果序列有序,那么在拓扑排序时,每个点的伸出边必然满足只有一条,并且伸出边的入度只能为1,这样就保证了唯一的序列。

结:判断回环时,用了很多错的方式,这道题花的时间比较长,但也算是一个收获比较大的题,给了我一种新的思考问题的思路,读题时,注意情况之间的联系,比如这道题就是,虽然判断回环和判断有序两种情况,但是如果先判断是否有环,那么在有环情况下必然不满足题目所说的“有序”,这时候就不用再进行“有序”判断,结束查找,简化判断步骤。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 100;
int vis[maxn][maxn],in[maxn];
char str[maxn];
queue<int>q;
queue<int>ans;
int Top_sort(int n)
{
	int in2[maxn],count,l;
	//每次都要进行队列的初始化 
	while(!q.empty())
		q.pop();
	while(!ans.empty())
		ans.pop();
	for(int i = 1; i <= n; i ++)
	{
		in2[i] = in[i];//用临时数组保存入度值 
		if(in[i] == 0)
			q.push(i);//出现入度为0的点入q队 
 	}
	count = l = 0;
	while(!q.empty())
	{
		int number = q.front();//q队存入度为0的序列 
		if(q.size() > 1) //当q队中入度为0的点大于1时,说明仍未找到唯一序列 
			l = 1;
		count ++;//记录入度为0的点个数 
		ans.push(number);//ans队依次保存唯一序列值 
		q.pop(); //去掉相应边以后出队 
		for(int i = 1; i <= n; i ++)
		{
			if(vis[number][i])
			{
				in2[i] -- ;
				if(in2[i] == 0)
					q.push(i);
			}
		}
	}
	//先判断是否出现回环 
	if(count !=n)//出现环时,入度为0的点总数肯定无法等于n,依据这一条件判环这一情况 
		return -1;
	//在没有出现回环的情况下, 判断是否找到唯一序列 
	if(l == 0)//当q队列中入度为0的点始终只有一个时,说明已经找到了唯一的序列 
		return 1;
	//没有出现回环但也没有找到唯一序列时就继续输入查找 
	return 0;
}

int main()
{
	int n,m,flag,sum,count;
	int number1,number2;
	while(scanf("%d%d",&n,&m),n!=0||m!=0)
	{
		memset(vis,0,sizeof(vis));
		memset(in,0,sizeof(in));
	    flag = 0;
	    sum = 0;
		for(int i = 0;i < m; i ++)
		{
			scanf("%s",str);
			if(flag)//当出现情况1或者情况2时,就不再进行排序 
				continue;
			number1 = str[0]-'A'+1;
			number2 = str[2]-'A'+1;
			if(!vis[number1][number2])
			{
				vis[number1][number2] = 1;
				in[number2]++;
			}
			sum = Top_sort(n);
			if(sum == -1||sum == 1)
			{
				count = i+1;//记录下当前位置 
				flag = 1;//标志改变 
			}
		}
		if(!flag)
			printf("Sorted sequence cannot be determined.\n");
		else if(sum == -1)
			printf("Inconsistency found after %d relations.\n",count);
		else
		{
			printf("Sorted sequence determined after %d relations: ",count);
			while(!ans.empty())
			{
				printf("%c",ans.front()+'A'-1);
				ans.pop();
			}
			printf(".\n");
		}
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值