Acwing_343排序【Floyd求解传递闭包】

题目链接:Acwing_343排序

思路分析:

  • 本题考察Floyd算法在传递闭包问题上的应用。给定若干对元素和若干对二元关系,并且关系具有传递性,通过传递性推导出尽量多的元素之间的关系的问题被称为传递闭包。比如a < b,b < c,就可以推导出a < c,如果用图形表示出这种大小关系,就是a到b有一条有向边,b到c有一条有向边,可以推出a可以到达c,找出图中各点能够到达点的集合,就类似于Floyd算法求图中任意两点间的最短距离。Floyd求解传递闭包问题的代码如下:

  • 只是对原来算法在状态转移方程上略加修改 就能够求解传递闭包问题了。f[i][j] = 1表示i可以到达j ( i < j),f[i][j] = 0表示i不可到达j。只要i能够到达k并且k能够到达j,那么i就能够到达j,这就是上面代码的含义。

  • 对于本题而言,给定n个元素和一堆二元关系,依次读取每个二元关系,在读取第i个二元关系后,如果可以确定n个元素两两间的大小关系了,就输出在几对二元关系后可以确定次序,并且次序是什么;如果出现了矛盾,就是A < B并且B < A这种情况发生了就输出多少对二元关系后开始出现矛盾;如果遍历完所有的二元关系还不能确定所有元素间的大小关系,就输出无法确定。

  • 可以发现,题目描述要求按顺序遍历二元关系,一旦前i个二元关系可以确定次序了就不再遍历了,即使第i + 1对二元关系就会出现矛盾也不去管它了。对于二元关系的处理和之前的做法一样,A < B,就将f[0][1]设为1,题目字母只会在A到Z间,因此可以映射为0到25这26个元素,如果f[0][1] = f[1][0] = 1,就可以推出f[0][0] = 1,此时A < B并且A > B发生矛盾,因此在f[i][i]= 1时发生矛盾。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
const int N = 26;

int n, m;
bool g[N][N], d[N][N];
bool st[N];

void floyd() {
	memcpy(d, g, sizeof d);
	for (int k = 0; k < n; k++)
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				d[i][j] |= d[i][k] && d[k][j];
}

int check()
{
	for (int i = 0; i < n; i++) {
		if (d[i][i])
			return 2;
	}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < i; j++)
			if (!d[i][j] && !d[j][i])
				return 0;
	return 1;
}

char get_min() {
	for (int i = 0; i < n; i++)
	{
		if (!st[i])
		{
			bool flag = true;
			for (int j = 0; j < n; j++)
			{
				if (!st[j] && d[j][i])
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				st[i] = true;
				return 'A' + i;
			}
		}

	}
}

int main()
{
	while (cin >> n >> m, n || m)
	{
		memset(g, 0, sizeof g);
		int type = 0, t;
		for (int i = 1; i <= m; i++)
		{
			char str[5];
			cin >> str;
			int a = str[0] - 'A', b = str[2] - 'A';

			if (!type)
			{
				g[a][b] = 1;
				floyd();
				type = check();
				if (type) t = i;
			}
		}
		if (!type) puts("Sorted sequence cannot be determined.");
		else if (type == 2) printf("Inconsistency found after %d relations.\n", t);
		else {
			memset(st, 0, sizeof st);
			printf("Sorted sequence determined after %d relations: ", t);
			for (int i = 0; i < n; i++) printf("%c", get_min());
			printf(".\n");
		}

	}

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值