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

本文介绍了一种使用拓扑排序解决特定问题的方法,该问题涉及根据一系列关系确定一组元素的正确顺序。文章详细解释了如何通过逐步输入关系并进行拓扑排序来检查序列的有效性和一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意: 根据所给的关系(即A<B之类的), 判断是否能在给出某一组关系之后确定给定的所有字母的顺序(字母总数为n, 指前n个字母, 均为daxie), 若能则输出(根据题目输出),   若在给出某一组关系之后出现矛盾(例如 A<B B<C C<A,  矛盾, 形成环路)则输出(根据题目输出) , 所有关系均输入后仍然不能判断出矛盾或者有序, 则输出"Sorted sequence cannot be determined.".

解决:  明显的拓扑排序, 每组关系输入后都进行一次拓扑排序,根据返回结果确定输出

Code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 100;
int vis[maxn], num[maxn], d[maxn], dis[maxn][maxn];
int n, m ;
char c[5];
void init(){
	memset(dis, 0, sizeof(dis));
	memset(vis, 0, sizeof(vis));
}
int topology(){
	int i, j, k=0;
	memset(d, -1, sizeof(d));
	for(i=0; i<n; i++){
		if(vis[i]){
			k++;
			if(d[i]==-1) d[i]=0;
			for(j=0; j<n; j++){
				if(dis[i][j]) {
					if(d[j]==-1) d[j]=0;
					d[j]++;
				}
			}
		}
	}
	int u, cnt=0, p=0;
	while(true){
		u=-1;
		for(i=0; i<n; i++){
			if(!d[i]) {
				u = i;
				p++;//记录d[i]=0的个数, 每次都应该只有一个d[i]=0
			}
		}
		if(u==-1) break;
		d[u] = -1;
		num[cnt++] = u;
		for(i=0; i<n; i++){
			if(dis[u][i]) d[i]--;
		}
	}
	if(cnt<k) return 1;//矛盾
	else if(p>k) return 0;//暂时满足要求
	else if(cnt==n)return 2;//完成
	return 0;
}
int main()
{
	int i, j, k;
	//freopen("in.txt", "r", stdin);
	while(~scanf("%d %d", &n, &m), m||n){
		bool flag=false;
		init();
		int v=0;
		for(i=1; i<=m; i++){
			scanf("%s", c);
			int a = c[0]-'A';
			int b = c[2]-'A';
			if(v) continue;
			vis[a] = vis[b] = 1;
			dis[a][b]=1;
			int k = topology();
			if(k==1) { // 矛盾  ->存在环
				flag = true;
				v=i;
			} else if(k==2){//已经成功排序
				v=i;
			}
		}
		if(v) {
			if(flag){
				printf("Inconsistency found after %d relations.\n", v);
			} else {
				printf("Sorted sequence determined after %d relations: ", v);
				for(i=0; i<n; i++){
					printf("%c", num[i]+'A');
				}
				printf(".\n");
			}
		} else {
			printf("Sorted sequence cannot be determined.\n");
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值