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

这篇具有很好参考价值的文章主要介绍了Floyd判联通(传递闭包) & poj1049 sorting it all out。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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代码:仅供参考文章来源地址https://www.toymoban.com/news/detail-760403.html

点击查看代码
#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");
		}
	}
}

到了这里,关于Floyd判联通(传递闭包) & poj1049 sorting it all out的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第三章 图论 No.3 flody之多源汇最短路,传递闭包,最小环与倍增

    flody的四个应用: 多源汇最短路 传递闭包 找最小环 恰好经过k条边的最短路 倍增 多源汇最短路:1125. 牛的旅行 1125. 牛的旅行 - AcWing题库 直径概念:同一连通块中,两个距离最远的点之间的距离 如何求直径?由于图中存在着两个连通块,所以直接对全图做一个flody,就能更

    2024年02月14日
    浏览(30)
  • Text to image论文精读SeedSelect: 使用SeedSelect微调扩散模型It’s all about where you start

    随着文本到图像扩散模型的发展,很多模型已经可以合成各种新的概念和场景。然而,它们仍然难以生成结构化、不常见的概念、组合图像。今年4月巴伊兰大学和OriginAI发表《It’s all about where you start: Text-to-image generation with seed selection》一文,提出了一种SeedSelect技术,微调

    2024年02月07日
    浏览(32)
  • 【算法每日一练]-动态规划(保姆级教程 篇13)POJ2686马车旅行 #POJ3254 玉米田 #POJ1185:炮兵阵地

    目录 今天知识点 dp每个票的使用情况,然后更新此票状态下的最优解,dp到没有票就行了 把状态压缩成j,dp每行i的种植状态,从i-1行进行不断转移 把状态压缩成j,dp每行i的布置状态,从i-1和i-2行进行不断转移 POJ2686马车旅行 思路: POJ3254 玉米田 思路: POJ1185:炮兵阵地 思路:

    2024年02月04日
    浏览(37)
  • 【算法每日一练]-图论(保姆级教程篇12 tarjan篇)#POJ3352道路建设 #POJ2553图的底部 #POJ1236校园网络 #缩点

    目录: 今天知识点 加边使得无向图图变成双连通图 找出度为0的强连通分量 加边使得有向图变成强连通图 将有向图转成DAG图进行dp          POJ3352:道路建设         思路: POJ2553:图的底部 思路: POJ1236校园网络 思路: 缩点:  思路:          由于道路要维修

    2024年02月05日
    浏览(37)
  • POJ 2100 Graveyard Design 尺取法

    给出一个数字num,1=num=1e14,找出连续的数字 ai,ai+1...aj使得每一项取平方最后求和等于num,题目要求排列的数字,和排列的个数,输出出来 因为是平方求和,那么我们只需要计算1e7以内的数字就可以,case time limie 2000ms,简单考虑下尺取法最合适,O(n)复杂性,1e7的数组,时间上

    2024年02月09日
    浏览(23)
  • POJ 2456 Aggressive cows 二分搜素

    对两头牛之间的最大间距进行二分,在judge函数里不断的用lower_bound去寻找当前牛的下一头牛放置的最近位置,最后判断能否放下c头牛,可以的话left=mid,否则right=mid,最终输出left

    2024年02月10日
    浏览(23)
  • 挑战程序设计竞赛 2.2 poj 3040 Allowance 贪心

    https://vjudge.csgrandeur.cn/problem/POJ-3040 解答 直觉分析如下: 因为可选择的美分硬币数值是可整除的。所以我们需要尽量选择面额更大的硬币. 1 因为面值小的硬币总能替代面额大的硬币,更优。所以我们选择次优的较大面额的硬币,将更优的选择留给后面。 2 同样的 凑齐刚好等

    2024年02月08日
    浏览(36)
  • POJ - 2282 The Counting Problem(数位DP 计数问题)

    Given two integers a and b, we write the numbers between a and b, inclusive, in a list. Your task is to calculate the number of occurrences of each digit. For example, if a = 1024 a = 1024 a = 1024 and b = 1032 b = 1032 b = 1032 , the list will be 1024 1024 1024 1025 1025 1025 1026 1026 1026 1027 1027 1027 1028 1028 1028 1029 1029 1029 1030 1030 1030 1031 10

    2023年04月17日
    浏览(27)
  • PAT B1049

    题目 给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4) 这 10 个片段。 给定正整数数列,求出全部片段包含的所有的数之和。

    2024年02月02日
    浏览(25)
  • POJ 3662 Telephone Lines 二分,最小化第k大的数

    我们有n个点,p条边,最小化从1到n之间的路径的第k+1大的数(当路径不超过k时就是0) 我们首先用dijkstra过一遍,判断从1能不能到n,不能直接输出-1结束。 1能到达n的话,就对二分第k+1大的边进行二分,left选-1,right选最大的边的长度+1(这里我left一开始选取的时最小边-1,

    2024年02月09日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包