POJ 1094(拓扑排序)

/*
思路:典型的拓扑排序问题
这道题题意容易引起误解:
如果解不唯一,则输出Sorted sequence cannot be determined.
如果存在环,则输出Inconsistency found after %d relations.
如果解唯一,则输出Sorted sequence determined after %d relations: %s.
*/
#include <iostream>
using namespace std;

const int MAX_NUM = 32;
int map[MAX_NUM][MAX_NUM];
bool vis[MAX_NUM];   //记录到目前为止在输入中出现的顶点
int count[MAX_NUM];  //保存每个顶点的入度
int buf[MAX_NUM];
char res[MAX_NUM];
int n, m;
bool single_solution;

int topo_order()
{
	int i, j, k, top = -1, cnt = 0, vetex_num = 0;
	single_solution = true;   //是否是唯一解
	for (i = 0; i < n; ++i){
		if (vis[i]){
			vetex_num++;
			if (count[i] == 0){  //用count数组模拟堆栈,数组的下标是要压栈的数值
				count[i] = top;
				top = i;
			}
		}
	}

	for (i = 0; i < vetex_num; ++i){
		if (top == -1){   //不存在入度为0的点,说明存在环
			return 0;
		}
		else{
			j = top;
			top = count[top];
			if (top != -1){
				single_solution = false; //存在其他入度为0的点,说明解不唯一
			}
			res[cnt++] = char('A' + j);
			//将该点去掉,并且对于所有以该点为起点的边,边的终点入度都减1
			for (k = 0; k < n; ++k){  
				if (map[j][k] && (--count[k]) == 0){
					count[k] = top;
					top = k;
				}
			}
		}
	}
	res[cnt] = '\0';
	return cnt;
}

int main()
{
	int i, j, from, to, flag, step;
	char s[6];
	while (scanf("%d%d", &n, &m) && n != 0){
		flag = n - 1;
		step = -1;
		single_solution = false;
		memset(count, 0, sizeof(count));
		memset(buf, 0, sizeof(buf));
		memset(vis, 0, sizeof(vis));
		memset(map, 0, sizeof(map));
		for (i = 1; i <= m; ++i){
			scanf("%s", s);
			//如果存在环或者解唯一,则忽略输入
			if (flag == 0 || (flag == n && single_solution)){
				continue;
			}
			memcpy(count, buf, sizeof(count));
			from = s[0] - 'A';
			to = s[2] - 'A';
			count[to]++;
			map[from][to] = 1;
			vis[from] = vis[to] = true;
			memcpy(buf, count, sizeof(count));
			flag = topo_order();
			if (flag == 0 || (flag == n && single_solution)){
				step = i;
			}
			//step = i; // 记录步数
		}

		if (flag == 0){
			printf("Inconsistency found after %d relations.\n", step);
		}
		else if (flag == n && single_solution){
			printf("Sorted sequence determined after %d relations: %s.\n", step, res);
		}
		else{
			printf("Sorted sequence cannot be determined.\n");
		}
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值