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

传送门:http://poj.org/problem?id=1094

这题就是普通的拓扑排序,但是有几个要点要注意

首先就是要记录在输入到哪一步的时候会产生什么样的结果,如果产生了答案或者产生了环就略过接下来的输入。

为了达到这样的效果,只能输入一条边就拓扑一次,看看有没有产生答案。

我因为判断结果的优先级搞错了wa了很多次

产生了答案或者产生环的优先级都是高于不能排序的。也就是说,即使没有产生答案,但是有环的话,也是直接输出有环。

代码如下

#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<set>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<map>
#include<cstring>
#include<iostream>
using namespace std;
int n, m;
int ind[30];
int temp[30];
bool vis[30];
char seq[30];
vector < vector<int> > v;
int topsort(int now)
{
	int q = now;
	int i, j;
	for (i = 0; i < n; i++) temp[i] = ind[i];
	int len = 0, cot = 0;
	bool ok = true;
	int del = 0;//记录在拓扑的时候删除了几个点
	while (now--)
	{
		cot = 0;//记录入度为0的点有几个
		for (i = 0; i < n; i++)
		{
			if (temp[i] == 0)
			{
				j = i;
				cot++;
			}
		}
		if (cot >= 1)
		{
			if (cot > 1)//即使此时有多种结果,也要删点。为了判断有没有环,拓扑还是要做完才能return
				ok = false;
			for (i = 0; i < v[j].size(); i++)
				temp[v[j][i]]--;
			temp[j] = -1;
			del++;
			seq[len++] = j + 'A';
			seq[len] = '\0';
		}
		else if (cot == 0)//此时肯定有环,直接return
			return -1;
	}
	if (ok)
		return 1;
	else if (del != q)//q为当前图中存在的点数
		return -1;
	return 0;
}
int main()
{
	//	freopen("D://input.txt", "r", stdin);
	while (scanf("%d%d", &n, &m) != EOF&&n&&m)
	{
		memset(ind, 0, sizeof(ind));
		memset(vis, false, sizeof(vis));
		v.clear(); v.resize(n);
		int ans = 0;
		int i;
		char s[5];
		int a, b;
		int ok = 0, cot = 0;//cot记录当前图中存在的点
		for (i = 0; i < m; i++)
		{
			scanf("%s", s);
			if (ok != 0)
				continue;
			a = s[0] - 'A';
			b = s[2] - 'A';
			ind[b]++;
			v[a].push_back(b);
			if (!vis[a]) {
				vis[a] = true;
				cot++;
			}
			if (!vis[b]) {
				vis[b] = true;
				cot++;
			}
			ok = topsort(cot);
			if (ok != 0)
				ans = i + 1;//ans记录几回合产生答案的
		}
		if (ok == 1) {
			printf("Sorted sequence determined after %d relations: %s.\n", ans, seq);
		}
		else if (ok == 0) {
			printf("Sorted sequence cannot be determined.\n");
		}
		else {
			printf("Inconsistency found after %d relations.\n", ans);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值