首页 > 其他分享 >Floyd判联通(传递闭包) & poj1049 sorting it all out

Floyd判联通(传递闭包) & poj1049 sorting it all out

时间:2023-12-25 14:23:14浏览次数:31  
标签:闭包 输出 sorting 不等式 int 矛盾 poj1049 -- data

Floyd判联通(传递闭包)

Floyd传递闭包顾名思义就是把判最短路的代码替换成了判是否连通的代码,它可以用来判断图中两点是否连通。板子大概是这个样的:

for(int k=1; k<=n; k++){
	for(int i=1; i<=n; i++){
		for(int j=1; j<=n; j++){
			// 把数值计算替换成逻辑运算——就一行,非常简便
			e[i][j] = e[i][j] || (e[i][k] && e[k][j]);
		}
	}
}

题目描述

给定 n个变量和 m个不等式。其中 n小于等于 26,变量分别用前 n的大写英文字母表示。

不等式之间具有传递性,即若 A>B 且 B>C,则 A>C。

请从前往后遍历每对关系,每次遍历时判断:

  • 如果能够确定全部关系且无矛盾,则结束循环,输出确定的次序;
  • 如果发生矛盾,则结束循环,输出有矛盾;
  • 如果循环结束时没有发生上述两种情况,则输出无定解。
    输入格式
    输入包含多组测试数据。

每组测试数据,第一行包含两个整数 n和 m。

接下来 m行,每行包含一个不等式,不等式全部为小于关系。

当输入一行 0 0 时,表示输入终止。

输出格式
每组数据输出一个占一行的结果。

结果可能为下列三种之一:

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

那么我们可以分析题目:题目说要“从前往后遍历每对关系” 那么就不是一次性导入所有数据了,而是每输入一个就计算一遍。

graph TB Begin(开始) --> A[输入不等式] A -->E{是否存在矛盾} E -->|存在|B[输出矛盾信息] E -->|不存在|C C{是否能确定两两关系} C -->|能确定|D[输出升序排列] C -->|不能确定|A F{全部不等式输入完成且未发生以上情况} -->G[输出] A -->F

那么怎么判断是否存在矛盾呢?想想看,不就是既有\(A>B\) 又有\(B>A\)吗。那么就可以在floyd的同时加入判断。

for(int k=1; k<=n; k++){
	for(int i=1; i<=n; i++){
		for(int j=1; j<=n; j++){
			e[i][j] = e[i][j] || (e[i][k] && e[k][j]);
			// 注意要i!=j
			// 如果e[i][j]和e[j][i]都联通肯定存在矛盾
			if(e[i][j] && e[j][i] && i!=j){
				data = 0;
			}
		}
	}
}

那怎么判断能否确定两两关系呢?那就是在没有矛盾的前提下,两两首尾相连。如果存在两个点没有首尾相连的情况,那肯定不行的。我这里把判断它的代码单独拿了出来放在一个函数里,因为如果在floyd中写的话它是会变化的,可能在某次循环时它不连通,但循环几次后它又联通了。所以还不如拿出去.

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

可以判断两两关系了,那怎么打印出次序呢?我在某个大佬那里受到启发——观察矩阵。试想一下,如果\(A<B<C<D\),那么A联通的点有3个,B联通的点有2个,C联通的点有…… 也就是这个样子的:

A[1][n] 0 1 1 1
B[2][n] 0 0 1 1
C[3][n] 0 0 0 1
D[4][n] 0 0 0 0

那么就只用依次取出“1”最多的打印出来就好。

inline void out(){
	// #define p pair<int, char>
	priority_queue<p, vector<p>, less<p> > q;
	int t;
	for(int i=1; i<=n; i++){
		t = 0;
		for(int j=1; j<=n; j++){
			if(i != j) t += e[i][j];
		}
		q.push( (p){t, i-1+'A'} );
	}
	while(!q.empty()){
		printf("%c",q.top().second);
		q.pop();
	}
	printf(".\n");
}

这道题个人感觉非常nice,他开拓了我们的新思路:观察矩阵(找规律)。好了,以上是我的全部理解。博客freshman,如有错误,还请指点!

AC代码:仅供参考

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define p pair<int, char>
int n,m,data;
bool e[27][27],node[27];
string s;
inline void floyd(){
	for(int k=1; k<=n; k++){
		for(int i=1; i<=n; i++){
			for(int j=1; j<=n; j++){
				e[i][j] = e[i][j] || (e[i][k] && e[k][j]);
				if(e[i][j] && e[j][i] && i!=j){
					data = 0;
				}
			}
		}
	}
}
bool check(){
	for(int i=1; i<=n; i++){
		for(int j=1; j<=n; j++){
			if(!e[i][j] && !e[j][i] && i!=j) return 0;
		}
	}
	return 1;
}
inline void out(){
	priority_queue<p, vector<p>, less<p> > q;
	int t;
	for(int i=1; i<=n; i++){
		t = 0;
		for(int j=1; j<=n; j++){
			if(i != j) t += e[i][j];
		}
		q.push( (p){t, i-1+'A'} );
	}
	while(!q.empty()){
		printf("%c",q.top().second);
		q.pop();
	}
	printf(".\n");
}
int main(){
	while(scanf("%d%d",&n,&m) && n){
		memset(e, 0, sizeof(e));
		memset(node, 0, sizeof(node));
		data = 1;
		for(int i=1; i<=m; i++){
			cin>>s;
			e[s[0]-'A'+1][s[2]-'A'+1] = 1;
			node[s[0]-'A'+1] = node[s[2]-'A'+1] = 1;
			if(data == 1){
				floyd();
				if(data == 0){
					printf("Inconsistency found after %d relations.\n",i);
					//break;
				}
				else if(check()){
					printf("Sorted sequence determined after %d relations: ",i);
					out();
					data = 2;
					//break;
				}
			}
		}
		if(data == 1){
			printf("Sorted sequence cannot be determined.\n");
		}
	}
}

标签:闭包,输出,sorting,不等式,int,矛盾,poj1049,--,data
From: https://www.cnblogs.com/xiaolemc/p/17925996.html

相关文章

  • python基础007----递归函数&闭包&装饰器
    一、递归函数1、递归函数概念    直接或间接的调用自身的函数,称为递归函数。每调用一次自身,相当于复制一份该函数,只不过参数有变化,参数的变化,就是重要的结束条件。2、递归函数实例#####递归函数######1、普通实现:计算n!=1*2*3*4*5*6*...*nn=int(input('普通实现阶乘,......
  • 无涯教程-Go - 函数闭包
    Go编程语言支持可以充当函数闭包的匿名函数,当我们要内联定义函数而不传递任何名称时,将使用匿名函数。在我们的示例中,我们创建了一个函数getSequence(),该函数返回另一个函数,此函数的目的是关闭上层函数的变量i形成闭包。如-packagemainimport"fmt"funcgetSequence()func......
  • 用闭包写个单例模式
    DN对闭包的定义是:闭包是指那些能够访问自由变量的函数,自由变量是指在函数中使用的,但既不是函数参数又不是函数的局部变量的变量,由此可以看出,闭包=函数+函数能够访问的自由变量,所以从技术的角度讲,所有JS函数都是闭包,但是这是理论上的闭包,还有一个实践角度上的闭包,从实践角度上来......
  • 什么是 JavaScript 闭包?
    什么是JavaScript闭包?在JavaScript中,闭包是指一个函数能够访问在它外部定义的变量。这些变量通常被称为“自由变量”,因为它们不是该函数的局部变量,也不是该函数的参数。闭包可以在函数内部创建,也可以在函数外部创建。JavaScript中的每个函数都是一个闭包,因为它们都能够访问......
  • C#委托和闭包实现方式
    在底层,编译器会为委托生成一个类,这个类包含了每一个闭包所捕获的变量作为它的一个公有字段。这也是为什么闭包捕获的变量的生命周期和委托的一致的原因。具体可以看:https://blog.csdn.net/zhudaokuan/article/details/113032690总的来说,C#中的委托和闭包的底层原理都与编译器如......
  • 详解rust 自动化测试、迭代器与闭包、智能指针、无畏并发
    编写测试可以让我们的代码在后续迭代过程中不出现功能性缺陷问题;理解迭代器、闭包的函数式编程特性;Box<T>智能指针在堆上存储数据,Rc<T>智能指针开启多所有权模式等;理解并发,如何安全的使用线程,共享数据。自动化测试编写测试以方便我们在后续的迭代过程中,不会改坏代码。保证了程序的......
  • Golang的闭包和匿名函数
    Golang语言支持匿名函数,这些匿名函数也被称为闭包。匿名函数是一种特殊类型的函数,它没有名称,而闭包可以看作是一种特殊类型的匿名函数,尽管在实践中有微小的区别。 Golang中的匿名函数匿名函数也可以称为字面函数、lambda函数或闭包。闭包的概念源于lambda计算中表达式的数......
  • python高级之函数对象与闭包函数
    函数对象和闭包函数函数对象1,什么是函数对象?函数对象简单理解就是将函数当变量来使用。如下图所示:定义一个函数可以简单的理解为:func=函数体内存地址函数名+()–>调用函数函数名-->函数对象,函数名不加括号此时的函数名就是函数对象函数用于赋值将函数赋值给某个变......
  • 闭包函数
    闭包函数(一)什么是闭包函数闭包是指包含对自由变量的函数和对这些变量的引用环境的组合。基于函数对象的概念,可以将函数返回到任意位置去调用。但作用域的关系是在定义完函数时就已经呗确定了的,与函数的调用位置无关。#闭包函数#定义一个全局变量x=1#定义外层函数defo......
  • 名称空间与闭包
    名称空间与作用域一、名称空间与闭包[1]什么是名称空间?名称空间即存放名字与对象映射/绑定关系的地方在程序执行期间最多会存在三种名称空间x=3#给变量赋值的时候就给3这个变量值开辟了一个命名为x的名称空间delx#这里删除了这个变量名与对象的的映射,所以下面输出......