【图论,拓扑排序】P1347 排序

题意

一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列 A , B , C , D A,B,C,D A,B,C,D 表示 A < B , B < C , C < D A<B,B<C,C<D A<B,B<C,C<D。在这道题中,我们将给你一系列形如 A < B A<B A<B 的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序。

输入格式

第一行有两个正整数 n , m n,m n,m, n n n 表示需要排序的元素数量, 2 ≤ n ≤ 26 2\leq n\leq 26 2≤n≤26,第 1 1 1 到 n n n 个元素将用大写的 A , B , C , D , ... A,B,C,D,\dots A,B,C,D,... 表示。 m m m 表示将给出的形如 A < B A<B A<B 的关系的数量。

接下来有 m m m 行,每行有 3 3 3 个字符,分别为一个大写字母,一个 < 符号,一个大写字母,表示两个元素之间的关系。

输出格式

若根据前 x x x 个关系即可确定这 n n n 个元素的顺序 yyy..y(如 ABC),输出

Sorted sequence determined after x relations: yyy...y.

其中 x x x 表示上述的前 x x x 个关系,注意 relations: 与输出的顺序中有一个空格

若根据前 x x x 个关系即发现存在矛盾(如 A < B , B < C , C < A A<B,B<C,C<A A<B,B<C,C<A),输出

Inconsistency found after x relations.

其中 x x x 表示的意义同上。

若根据这 m m m 个关系无法确定这 n n n 个元素的顺序,输出

Sorted sequence cannot be determined.

(提示:确定 n n n 个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况)

说明/提示

2 ≤ n ≤ 26 , 1 ≤ m ≤ 600 2 \leq n \leq 26,1 \leq m \leq 600 2≤n≤26,1≤m≤600。

思路

oi wiki 的拓扑排序介绍,建议先浏览。

本文是每加入一条边后进行一次拓扑排序,然后判断出现环、有多个入度为0的点还是能拍出顺序。

小细节:

  • 要先判断环再判断有多个入度为0的点,也就是你拓扑排序中不能一遇到有2个入度为0的点就停止排序进行下一条边的读入。

  • 环的判断要求是比较已经排好顺序的点和目前出现的所有点 比较,而非同一共的点数 n n n 比较。

  • 本题需要拓扑排序多次,排序需要的入度数组建议另行复制一个,以免影响原数组。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int head[30],nex[1005],to[1005],cnt = 0,now_P;
int in[30];//点入度
bool vis[35];
void add(int x,int y) {
	nex[++cnt] = head[x];
	head[x] = cnt;
	to[cnt] = y;
	in[y]++;
	if(!vis[x]) now_P ++;
	if(!vis[y]) now_P++;
	vis[x] = 1,vis[y] = 1;
}
int sx[30],tpin[30];//顺序 

int tp() {
	int t = 0;
	bool k = 0;//判断是否出现有两个入度为0的情况
	queue<int>point;
	for(int i = 0;i <= 25;i++) {
		tpin[i] = in[i];//复制入度
		if(tpin[i] == 0 and vis[i]) point.push(i);
	}
	while(!point.empty()) {
		int P = point.front();
        point.pop();
		if(!point.empty()) k = 1;
		sx[++t] = P;
		for(int i = head[P];i;i = nex[i]) {
			tpin[to[i]]--;
			if(tpin[to[i]] == 0) point.push(to[i]);
		}
		//printf("______%lld %lld\n",P,t);
	}
	if(t < now_P) return 0;//出现环
	if(k) return 2;
	return 1;
}
signed main() {
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= m;i++) {
		char p,r,q;
		cin >> p >> r >> q;
		add(int(q - 'A'),int(p - 'A'));
		int result = tp();
		if(result == 0) {
			printf("Inconsistency found after %d relations.\n",i);
			return 0;
		}
		else if(result == 1 and now_P == n) {
			printf("Sorted sequence determined after %d relations: ",i);
			for(int j = n;j >= 1;j--) cout<<char(sx[j] + 'A');
			cout<<'.';
			return 0;
		}
	}
	printf("Sorted sequence cannot be determined.\n");
    return 0;
}
相关推荐
依然鸣2 分钟前
PTA团体程序设计天梯赛L1真题讲解L1-077-080
开发语言·c++·算法·深度优先·pat考试·图论
麻雀飞吧1 小时前
零基础选量化工具,先把问题说清楚
人工智能·python
段一凡-华北理工大学1 小时前
AI推动工业智能化转型~系列文章20:工业 AI 平台架构:云-边-端协同的技术体系
人工智能·python·架构·工业平台·云-边协同
CodeBlog-star1 小时前
Harness Engineering:Pi Agent 架构深度解析
人工智能·python·架构·harness工程
简不变1 小时前
将components下的文件夹复制到别一个文件夹下,并重新生成CMakelist.txt文件
python
库玛西2 小时前
现代 C++ 智能指针全景指南:从 RAII 思想到工业级实践
c语言·开发语言·c++·笔记·面试
AC赳赳老秦2 小时前
风控岗应用:OpenClaw 采集公开司法与经营异常数据,自动生成企业风险评估报告
大数据·c语言·数据库·人工智能·python·php·openclaw
databook2 小时前
如何对稀疏数据的场景进行分析
python·数据挖掘·数据分析
liulilittle2 小时前
无锁并发容器的设计与实现原理
开发语言·c++·set·map·并发·无锁·lock-free
qeen873 小时前
【数据结构】自平衡二叉搜索树各种旋转算法原理解析及AVL树的C++实现
数据结构·c++·算法