首页 > 其他分享 >floyd 专题

floyd 专题

时间:2023-08-28 23:23:58浏览次数:53  
标签:专题 int scanf d% 枚举 floyd inf

更进一步的感悟 floyd 内涵!


了解 & 理解 floyd:

floyd 算法,常用于求多源最短路,O(n^3)。

本质是动态规划。两个点,通过找中转点更新答案。

三个 for。其中第一个 for 枚举 k 表示除了起点终点外只允许前走 1~k 个点的答案。另外两个 for 枚举起点终点。


例题 1:P1119 灾后重建:加强对枚举 k 过程的理解。

注意到 t_0 <= t_1 <= ... <= t_N-1,且询问序列不下降,这恰好符合了 floyd 的要求。

于是我们把枚举 k 跑 floyd 的过程移到每次询问中处理,由于询问序列不下降,所以每次枚举的 k 只要保证了 t[k] <= z 即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 202;
int n, m, q;
int a[N], f[N][N];
int main()
{
	scanf("%d%d", &n, &m);
	memset(f, 0x3f, sizeof f);
	for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
	while(m -- )
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		f[x][y] = min(f[x][y], z);
		f[y][x] = min(f[y][x], z);
	}
	scanf("%d", &q);
	int k = -1;
	while(q -- )
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		while(k + 1 < n && a[k + 1] <= z)
		{
			k ++;
			for(int i = 0; i < n; i ++ )
				for(int j = 0; j < n; j ++ )
					f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
		}
		if(f[x][y] == 0x3f3f3f3f || a[x] > z || a[y] > z) puts("-1");
		else printf("%d\n", f[x][y]);
	}
	return 0;
}

例题 2:P2966 [USACO09DEC] Cow Toll Paths G:最短路径涉及到最大点权。

首先考虑到枚举中转点 k 的顺序不会影响答案,所以想一下怎么按照点权先来进行一个排序。

可以将点权从小到大排序,这样考虑最大点权时,a[k].v 即能代表在 i 到 j 的路径上除了 i 和 j 的最大点权,最大点权就是比较 i、j、k。这样排序的时候单独标一下编号即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 253;
const int inf = 0x3f;
int n, m, q;
int d[N][N], f[N][N];
struct node{int v, num;}a[N];
bool cmp(node x, node y){return x.v < y.v;}
int main()
{
	scanf("%d%d%d", &n, &m, &q);
	memset(f, inf, sizeof f);
	memset(d, inf, sizeof d);
	for(int i = 1; i <= n; i ++ )
	{
		scanf("%d", &a[i].v);
		a[i].num = i;
		d[i][i] = 0;
	}
	sort(a + 1, a + n + 1, cmp);
	while(m -- )
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z); 
		d[x][y] = min(d[x][y], z);
		d[y][x] = min(d[y][x], z);
	}
	for(int k = 1; k <= n; k ++ )
		for(int i = 1; i <= n; i ++ )
			for(int j = 1; j <= n; j ++ )
			{
				int x = a[i].num, y = a[j].num, z = a[k].num;
				d[x][y] = min(d[x][y], d[x][z] + d[z][y]);
				f[x][y] = min(f[x][y], d[x][y] + max(a[i].v, max(a[j].v, a[k].v)));
			}
	while(q -- )
	{
		int x, y;
		scanf("%d%d", &x, &y);
		printf("%d\n", f[x][y]);
	}
	return 0;
}

例题 3:P2888 [USACO07NOV] Cow Hurdles S:路径上的最大值最小。

(两年前做过这道题,震惊的,一点没进步是吧。)

就是把跑最短路的过程换成了跑两点之间最小的最大值。很板子了。

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, t;
int f[310][310];
int main()
{
	memset(f, inf, sizeof f);
	scanf("%d%d%d", &n, &m, &t);
	while(m -- )
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		f[x][y] = min(z, f[x][y]);
	}
	for(int k = 1; k <= n; k ++ )
		for(int i = 1; i <= n; i ++ )
			for(int j = 1; j <= n; j ++ ) f[i][j] = min(f[i][j], max(f[i][k], f[k][j]));
	while(t -- )
	{
		int x, y;
		scanf("%d%d", &x, &y);
		if(f[x][y] == inf) puts("-1");
		else printf("%d\n", f[x][y]);
	}
	return 0;
}

例题 4:P2419 [USACO08JAN] Cow Contest S:求传递闭包。

看到题的第一反应是拓扑排序,好像不是很好写;第二反应是 dfs,好像也不是很好写;如你所见,第三反应是套 floyd。

考虑当一个数知道它与其他 n - 1 个数的大小关系后就可以确定排名了。直接跑就完事了。

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int n, m;
int ans;
int f[N][N];
int main()
{
	scanf("%d%d", &n, &m);
	while(m -- )
	{
		int x, y;
		scanf("%d%d", &x, &y);
		f[x][y] = 1;
	}
	for(int k = 1; k <= n; k ++ )
		for(int i = 1; i <= n; i ++ )
			for(int j = 1; j <= n; j ++ ) f[i][j] |= f[i][k] && f[k][j];
	for(int i = 1; i <= n; i ++ )
	{
		int flag = 1;
		for(int j = 1; j <= n; j ++ )
		{
			if(i != j && f[i][j] == 0 && f[j][i] == 0)
			{
				flag = 0;
				break;
			}
		}
		ans += flag;
	}
	printf("%d", ans);
	return 0;
}

例题 5:hdu 1599.find the mincost route:求最小环。

无向图,那 i 点到 j 点之间的最小环可以表示为 i 到 j 之间的最小距离加上 j 到中转点 k、k 到 i 的直接距离。

k 直接枚举就好。

为了防止这两条路重合,只要保证当前 i 到 j 之间求最小距离的中转点只能为 1 ~ k-1。因为从 i 到 j 和 j 到 i 无区别,所以枚举 j 时可以直接从 i + 1 开始节省一定时间。

这样我们每一次枚举 k 时,先跑一遍最小环,再跑 floyd。

特别注意 ll 数组最好别用 memset。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 302;
const ll inf = 0x7fffffffff;
int n, m;
ll f[N][N], a[N][N];
void solve()
{
	for(int i = 1; i < N; i ++ ) for(int j = 1; j < N; j ++ ) f[i][j] = a[i][j] = inf;
	while(m -- )
	{
		int x, y;
		ll z;
		scanf("%d%d%lld", &x, &y, &z);
		a[x][y] = a[y][x] = f[x][y] = f[y][x] = min(a[x][y], z);
	}
	ll minn = inf;
	for(int k = 1; k <= n; k ++ )
	{
		for(int i = 1; i < k; i ++ )
			for(int j = i + 1; j < k; j ++ ) minn = min(minn, f[i][j] + a[j][k] + a[k][i]);
		for(int i = 1; i <= n; i ++ )
			for(int j = 1; j <= n; j ++ ) f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
	}
	if(minn != inf) printf("%lld\n", minn);
	else puts("-1");
}
int main()
{
	while(~scanf("%d%d", &n, &m)) solve();
	return 0;
}

一定程度上加深了我对 floyd 尤其是这个 k 的认识。以后我再做了什么相关好题还会继续补充 qwq。

标签:专题,int,scanf,d%,枚举,floyd,inf
From: https://www.cnblogs.com/Moyyer-suiy/p/17663098.html

相关文章

  • 【专题】2022品牌营销决策解决方案报告PDF合集分享(附原数据表)
    全文链接:https://tecdat.cn/?p=33511根据报告合集显示,在消费者的亲友分享、社交平台、订单评价等环节,00后表现出活跃的参与度,而90后和95后在部分环节也较为活跃。相比之下,70后和80后在分享中的参与度最低,主要以亲友分享为主。阅读原文,获取专题报告合集全文,解锁文末335份品牌营销......
  • 【专题】2023品牌内容营销洞察报告PDF合集分享(附原数据表)
    全文链接:https://tecdat.cn/?p=33511根据报告合集显示,在消费者的亲友分享、社交平台、订单评价等环节,00后表现出活跃的参与度,而90后和95后在部分环节也较为活跃。相比之下,70后和80后在分享中的参与度最低,主要以亲友分享为主。阅读原文,获取专题报告合集全文,解锁文末335份品牌营销......
  • 【专题】洞察营销的战略优势与实操报告PDF合集分享(附原数据表)
    全文链接:https://tecdat.cn/?p=33511根据报告合集显示,在消费者的亲友分享、社交平台、订单评价等环节,00后表现出活跃的参与度,而90后和95后在部分环节也较为活跃。相比之下,70后和80后在分享中的参与度最低,主要以亲友分享为主。阅读原文,获取专题报告合集全文,解锁文末335份品牌营销......
  • 城市生命线专题周丨宏电内涝立体监测系统,构筑城市防汛智慧屏障
    方案背景在城市化进程不断推进和极端降雨事件频发的双重影响下,城市“看海”现象屡屡发生。以往的传统方法如整治河道、改造地下管网、增加排涝设施等已经不足以很好地解决现代城市内涝问题,随着物联网技术的快速发展和深入应用,使得以信息化的手段实现城市内涝的监测预警与模拟预测成......
  • 【Ehcache技术专题】「入门到精通」带你一起从零基础进行分析和开发Ehcache框架的实战
    缓存大小的设置缓存大小的限制可以设置在CacheManager上,也可以设置在单个的Cache上。我们可以设置缓存使用内存的大小,也可以设置缓存使用磁盘的大小,但是使用堆内存的大小是必须设置的,其它可设可不设,默认不设就是无限制。在设置缓存大小的时候,我们可以设置缓存使用某一个存储器的最......
  • RS232串口专题
    启动串口调试助手项目运行截图基础类封装数据类型转换类usingSystem;usingSystem.Text;namespaceSerialPortHelperDemo{///<summary>///16进制使用的隔离符枚举///</summary>publicenumEnum16Hex{None,//无Blank,/......
  • 【Ehcache技术专题】「入门到精通」带你一起从零基础进行分析和开发Ehcache框架的实战
    Ehcache的存储方式Ehcache中对于缓存的存储主要有三种方式:分别是堆内存、非堆内存和磁盘。其中非堆内存是针对于企业版Ehcache才有的功能,它可以不受JavaGC的影响,能够创建很大的缓存。堆内存(MemoryStore)我们通常所有的MemoryStore实际上就是堆内存存储。MemoryStore总是可用的,所有......
  • 《算法笔记》树与二叉树专题练习
    1、复原二叉树(由前序和中序求后序)题目描述小明在做数据结构的作业,其中一题是给你一棵二叉树的前序遍历和中序遍历结果,要求你写出这棵二叉树的后序遍历结果。输入输入包含多组测试数据。每组输入包含两个字符串,分别表示二叉树的前序遍历和中序遍历结果。每个字符串由不重复的大写......
  • 【Maven技术专题】「实战开发系列」盘点Maven项目中打包需要注意到的那点事儿
    Maven是什么Maven是一个流行的Java构建工具,它提供了许多插件来帮助开发人员自动化构建和部署Java应用程序。其中一个重要的插件是Maven打包插件,它可以将Java项目打包成可执行的JAR或WAR文件。在本文中,我们将深入探讨Maven打包插件的技术细节和使用方法。Maven打包插件的作用Maven打......
  • 猜结论专题
    A-Non-AdjacentFliphttps://atcoder.jp/contests/arc156/tasks/arc156_a题意给定一个01串,每次可以把不相邻的两个字符进行翻转,问最少要操作多少次使得全部变为0,无解输出-1。分析记录\(1\)的数量为\(cnt\)。每次翻转不改变\(1\)的奇偶性,所以\(1\)的数量为奇数时无......