AcWing 343. 排序(Floyd传递闭包,Java)

题目描述:
给定 n 个变量和 m 个不等式。其中 n 小于等于 26,变量分别用前 n 的大写英文字母表示。
不等式之间具有传递性,即若 A>B 且 B>C,则 A>C。
请从前往后遍历每对关系,每次遍历时判断:

  • 如果能够确定全部关系且无矛盾,则结束循环,输出确定的次序;
  • 如果发生矛盾,则结束循环,输出有矛盾;
  • 如果循环结束时没有发生上述两种情况,则输出无定解。

输入格式
输入包含多组测试数据。
每组测试数据,第一行包含两个整数 n 和 m。
接下来 m 行,每行包含一个不等式,不等式全部为小于关系。
当输入一行 0 0 时,表示输入终止。
输出格式
每组数据输出一个占一行的结果。
结果可能为下列三种之一:

  • 如果可以确定两两之间的关系,则输出 “Sorted sequence determined after t relations: yyy…y.”,其中’t’指迭代次数,'yyy…y’是指升序排列的所有变量。
  • 如果有矛盾,则输出: “Inconsistency found after t relations.”,其中’t’指迭代次数。
  • 如果没有矛盾,且不能确定两两之间的关系,则输出 “Sorted sequence cannot be determined.”。

数据范围
2≤n≤26,变量只可能为大写字母 A∼Z。

输入样例1
4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0
输出样例1
Sorted sequence determined after 4 relations: ABCD.
Inconsistencyfound after 2 relations.
Sorted sequence cannot be determined.
输入样例2:
6 6
A<F
B<D
C<E
F<D
D<E
E<F
0 0
输出样例2:
Inconsistency found after 6 relations.

题目链接排序

分析:

  • 根据传递闭包的性质,去推出每个元素之间的大小关系,例如A<B, B<C就可以推出A<C,每加入一对关系,就要去更新所有元素之间的关系,这就可以使用Floyd算法去解决。
  • 每更新一次元素间的关系,就去判断是否有矛盾,有矛盾就不用再去Floyd了,输出添加几次关系之后得到的矛盾。若添加完所有关系后没有矛盾,则又有两种情况:
    a.不能确定所有元素两两之间的关系:某个元素跟其他任意一个或多个元素没有大小关系
    b.不满足a则满足b。任意一个元素都跟其他所有元素能确定大小关系
    注意:a和b都是在任意元素之间没有矛盾的前提下的

代码(含注释):

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
	static boolean[][] d = new boolean[26][26];//d[i][j]为true表示i < j
	static boolean[] st = new boolean[26];	//用来后面输出元素顺序
	static int n, m;	//n个元素,m条关系
	public static void main(String[] args) throws Exception{
		//采用快读的方式
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String[] tmp = reader.readLine().split(" ");//tmp数组用来判断是否读到”0 0“
		while(!tmp[0].equals("0")) {
			for (int i = 0; i < 26; i++) //可能有多组数据
				Arrays.fill(d[i], false);//所以每执行完一段就要重置d数组
			
			n = Integer.parseInt(tmp[0]); m = Integer.parseInt(tmp[1]);
			int type = 0, step = 0;  //type用来记录它的结果是哪一种,step记录推导次数
			for (int i = 1; i <= m; i++) {
				char[] c = reader.readLine().toCharArray();
				int a = c[0]-'A', b = c[2]-'A';
				if (type==0) {	//此处type为0表示暂时不能确定关系
					d[a][b] = true;		//a<b为真
					floyd();	//更新所有元素关系
					type = check();  //每更新一次关系就去检查是否存在矛盾
					if (type!=0) step = i; 	//更新推导次数
				}
			}
			if (type==0) 	//此处若type仍为0,则表示不能确定
				System.out.println("Sorted sequence cannot be determined.");
			else if (type==1) 	//为1表示有矛盾
				System.out.println("Inconsistency found after "+step+" relations.");
			else {	//为2表示能确定关系
				Arrays.fill(st, false);		//因为可能有多组数据,所有st数组也需要重置
				System.out.print("Sorted sequence determined after "+step+ " relations: ");
				for (int i=0;i<n;i++) 
					System.out.print(getMin()); //每次输出所有关系中最小的
				System.out.println('.');
			}
			tmp = reader.readLine().split(" ");//读取下一行数据
		}
	}
	public static void floyd() {	//Floyd更新两点间关系
		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];
				}
	}
	public static int check() {
		for (int i = 0; i < n; i++) //若能推出i<i,则返回1表示有矛盾
			if (d[i][i]) return 1;
		for (int i = 0; i < n; i++) 
			for (int j = 0; j < n; j++) //若没有矛盾,但有不能确定的点
				if (i!=j&&!d[i][j]&&!d[j][i])	//返回0表示暂时不能确定
					return 0;
		return 2;	//上面两个都不满足则表示能确定关系,返回2
	}
	public static char getMin() {	//获取最小的元素
		for (int i = 0; i < n; i++) {
			if (!st[i]) {
				boolean flag = true;
				for (int j = 0; j < d.length; j++) {
					if (!st[j]&&d[j][i]) {	//若没访问过,但有其他点比他小,就跳过
						flag = false;
						break;
					}
				}
				if (flag) {	//若上面for循环走完flag仍为1,则表示它就是最小的
					st[i] = true;
					return (char) (i+'A');
				}
			}
		}
		return ' ';	//因为一定有解,所以这里不会执行,只是为了解决编译报错
	}
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Easenyang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值