POJ 1094 -- Sorting It All Out (拓扑排序)


Sorting It All Out
Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u

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.


 题意:根据给出的关系式判断大小关系,当出现环时输出在第几个关系式出现环,


             当可排序时输出在第几个关系式可排序并输出排序顺序。


             当所有关系式输入后无法排序则输出无法确定排序。


 思路:因为要输出第几个关系式,所以每输入一个关系式都要对图进行拓扑排序,


            若发现环则输出含有环,若可排序则输出可排序,重点在于 当出现多个0


            前驱节点时,应将所有0前驱标记,继续对图排序,看看是否含有环!! 


            输出遵照以下规则:优先级:输出环,输出完整顺序,输出无法排序。


代码如下:

法1:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define s 120
#define inf 0x3f3f3f3f
int n, m, indegree[s], vis[s], tmp[s];
char c[4], ans[s];
vector<vector<int>> v;//相当于二维数组
int toposort(int obj)
{
	int num, flag = 1, k, p = 0, i;
	for (i = 0; i < n; i++)  tmp[i] = indegree[i];//临时存放入度数组,以免影响下次结果
	while (obj--)
	{
		num = 0;//每次重新计数
		for (i = 0; i < n; i++){
			if (tmp[i] == 0){
				k = i, num++;
			}
		}
		if (num > 0){
			if (num > 1)  flag = 0;
                        else{
			   ans[p++] = k + 'A';
			   ans[p] = '\0';
                        }
			for (i = 0; i < v[k].size(); i++){
				tmp[v[k][i]]--;
			}
			tmp[k]--;
		}
		else
			return -1;//数据矛盾
	}
	if (flag) return p;//返回能排序的位数
	return 0;//排序不确定
}
int main()
{
#ifdef OFFLINE
	freopen("t.txt", "r", stdin);
#endif
	int i, j, k;
	while (~scanf("%d %d", &n, &m) && n&&m)
	{
		v.clear();   v.resize(n);
		memset(vis, 0, sizeof(vis));
		memset(indegree, 0, sizeof(indegree));
		int obj = 0, det = 0;
		for (i = 1; i <= m; i++){
			scanf("%s", c);
			indegree[c[2] - 'A']++;//入度
			v[c[0] - 'A'].push_back(c[2] - 'A');//建边
			if (!vis[c[0] - 'A']){
				vis[c[0] - 'A'] = 1;
				obj++;//对象数
			}
			if (!vis[c[2] - 'A']){
				vis[c[2] - 'A'] = 1;
				obj++;
			}
			if (det == 0)//排序不确定才继续
			{
				int res = toposort(obj);
				if (res == -1){
					k = i, det = -1;//k记录数据组数
				}
				else if (res == n){
					k = i, det = 1;
				}
			}
		}
		if (det == -1)
			printf("Inconsistency found after %d relations.\n", k);
		else if (det == 0)
			printf("Sorted sequence cannot be determined.\n");
		else
			printf("Sorted sequence determined after %d relations: %s.\n", k, ans);
	}
	return 0;
}

法二(与法一差不多,好理解点)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define s 120
#define inf 0x3f3f3f3f
int n, m, indegree[s], vis[s], tmp[s], rel[s][s];
char c[4], ans[s];
int toposort()
{
	int i, j, zero, k, flag = 1;//sure
	memcpy(tmp, indegree, sizeof(tmp));//将长度为数组tmp长度的indegree数组数据复制到tmp数组
	memset(ans, '\0', sizeof(ans));
	for (i = 0; i < n; i++)
	{
		zero = 0;//入度为0的点的个数
		for (j = 0; j < n; j++){
			if (tmp[j] == 0){
				k = j;//下标
				zero++;
			}
		}
		if (zero == 0) return -1;//有环 
		if (zero>1)  flag = 0;//无序(还不能确定是否有环, 所以继续)
		else    ans[i] = 'A' + k;
		tmp[k]--;
		for (j = 0; j < n; j++){
			if (rel[k][j])//由此点出发能直达的点入度减 1
				tmp[j]--;
		}
	}
	return flag;
}
int main()
{
#ifdef OFFLINE
	freopen("t.txt", "r", stdin);
#endif
	int i, j, k;
	while (~scanf("%d %d", &n, &m) && n + m)
	{
		bool sure = false;
		memset(rel, 0, sizeof(rel));
		memset(indegree, 0, sizeof(indegree));
		for (i = 1; i <= m; i++)
		{
			scanf("%s", c);
			if (sure) continue;
			if (!rel[c[0] - 'A'][c[2] - 'A']){//判重,避免加入重复边
				rel[c[0] - 'A'][c[2] - 'A'] = 1;
				indegree[c[2] - 'A']++;
			}
			int res = toposort();
			if (res == 1){
				sure = true;
				printf("Sorted sequence determined after %d relations: %s.\n", i, ans);
			}
			else if (res == -1){
				sure = true;
				printf("Inconsistency found after %d relations.\n", i);
			}
		}
		if (!sure)
			printf("Sorted sequence cannot be determined.\n");
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值