【图论】SPFA求负环
算法提高课笔记
文章目录
- 基础知识
- 例题
- 虫洞
- 题意
- 思路
- 代码
- 观光奶牛
- 题意
- 思路
- 代码
- 单词环
- 题意
- 思路
- 代码
基础知识
负环:环上权值之和是负数
求负环的常用方法 基于SPFA
- 统计每个点入队次数,如果某个点入队n次,则说明存在负环(完全等价于Bellman-Ford算法)
- 统计当前每个点的最短路中所包含的边数,如果某点的最短路包含的边数大于等于n,则说明存在负环
玄学结论:当所有点的入队次数超过2n时,就认为图中有很大肯存在负环
例题
虫洞
原题链接
农夫约翰在巡视他的众多农场时,发现了很多令人惊叹的虫洞。
虫洞非常奇特,它可以看作是一条 单向 路径,通过它可以使你回到过去的某个时刻(相对于你进入虫洞之前)。
农夫约翰的每个农场中包含 N 片田地,M 条路径(双向)以及 W 个虫洞。
现在农夫约翰希望能够从农场中的某片田地出发,经过一些路径和虫洞回到过去,并在他的出发时刻之前赶到他的出发地。
他希望能够看到出发之前的自己。
请你判断一下约翰能否做到这一点。
下面我们将给你提供约翰拥有的农场数量 F,以及每个农场的完整信息。
已知走过任何一条路径所花费的时间都不超过 10000 秒,任何虫洞将他带回的时间都不会超过 10000 秒。
输入格式
第一行包含整数 F,表示约翰共有 F 个农场。
对于每个农场,第一行包含三个整数 N,M,W。
接下来 M 行,每行包含三个整数 S,E,T,表示田地 S 和 E 之间存在一条路径,经过这条路径所花的时间为 T。
再接下来 W 行,每行包含三个整数 S,E,T,表示存在一条从田地 S 走到田地 E 的虫洞,走过这条虫洞,可以回到 T 秒之前。
输出格式
输出共 F行,每行输出一个结果。
如果约翰能够在出发时刻之前回到出发地,则输出 YES,否则输出 NO。
数据范围
1 ≤ F ≤ 5 1≤F≤5 1≤F≤5
1 ≤ N ≤ 500 , 1≤N≤500, 1≤N≤500,
1 ≤ M ≤ 2500 , 1≤M≤2500, 1≤M≤2500,
1 ≤ W ≤ 200 , 1≤W≤200, 1≤W≤200,
1 ≤ T ≤ 10000 , 1≤T≤10000, 1≤T≤10000,
1 ≤ S , E ≤ N 1≤S,E≤N 1≤S,E≤N
输入样例
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
输出样例
NO
YES
题意
负环板题
思路
跑一遍spfa
代码
#include <bits/stdc++.h>using namespace std;const int N = 510, M = 5210;int n, m1, m2;
int h[N], ne[M], e[M], w[M], idx;
int dist[N];
int cnt[N];
bool st[N];void add(int a, int b, int c)
{e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}bool spfa()
{memset(dist, 0, sizeof dist);memset(cnt, 0, sizeof cnt);memset(st, 0, sizeof st);queue<int> q;for (int i = 1; i <= n; i ++ ){q.push(i);st[i] = true;}while (q.size()){int t = q.front();q.pop();st[t] = false;for (int i = h[t]; ~i; i = ne[i]){int j = e[i];if (dist[j] > dist[t] + w[i]){dist[j] = dist[t] + w[i];cnt[j] = cnt[t] + 1;if (cnt[j] >= n) return true; // 更新次数一旦超过n就说明有负环if (!st[j]){q.push(j);st[j] = true;}}}}return false;
}int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T;cin >> T;while (T -- ){cin >> n >> m1 >> m2;memset(h, -1, sizeof h);idx = 0;for (int i = 0; i < m1; i ++ ){int a, b, c;cin >> a >> b >> c;add(a, b, c), add(b, a, c);}for (int i = 0; i < m2; i ++ ){int a, b, c;cin >> a >> b >> c;add(a, b, -c);}if (spfa()) puts("YES");else puts("NO");}
}
观光奶牛
原题链接
给定一张 L 个点、P 条边的有向图,每个点都有一个权值 f[i],每条边都有一个权值 t[i]。
求图中的一个环,使“环上各点的权值之和”除以“环上各边的权值之和”最大。
输出这个最大值。
注意:数据保证至少存在一个环。
输入格式
第一行包含两个整数 L 和 P。
接下来 L 行每行一个整数,表示 f[i]。
再接下来 P 行,每行三个整数 a,b,t[i],表示点 a 和 b 之间存在一条边,边的权值为 t[i]。
输出格式
输出一个数表示结果,保留两位小数。
数据范围
2 ≤ L ≤ 1000 , 2≤L≤1000, 2≤L≤1000,
2 ≤ P ≤ 5000 , 2≤P≤5000, 2≤P≤5000,
1 ≤ f [ i ] , t [ i ] ≤ 1000 1≤f[i],t[i]≤1000 1≤f[i],t[i]≤1000
输入样例
5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2
输出样例
6.00
题意
给出点权和边权,求一个环使得点权之和除以边权之和最大
思路
求比值最大的问题 -> 01分数规划 -> 二分
首先确定边界值,答案一定在[0, 1000)
之间
每次取中点mid,如果图中存在一个环使得比值大于mid,则答案在mid和r之间,反之亦然
现在问题变成了如何判断是否存在一个比值大于mid的环?
判断: ∑ f i ∑ t i > M i d \frac{\sum f_i}{\sum t_i}>Mid ∑ti∑fi>Mid
化简: ∑ f i − M i d ∗ ∑ t i > 0 \sum f_i-Mid*\sum t_i>0 ∑fi−Mid∗∑ti>0
在环上的点权我们可以任意加到边权上,对环不会有影响,假设我们将所有点权加到出边上,化简: ∑ ( f i − M i d ∗ t i ) > 0 \sum (f_i-Mid*t_i)>0 ∑(fi−Mid∗ti)>0
现在将边权全看成 f i − M i d ∗ t i f_i-Mid*t_i fi−Mid∗ti
问题转换成了:图中是否存在一个正环
求最长路即可
代码
#include <bits/stdc++.h>using namespace std;const int N = 1010, M = 5010;int n, m;
int wf[N];
int h[N], e[M], ne[M], wt[M], idx;
double dist[N];
int cnt[N];
bool st[N];void add(int a, int b, int c)
{e[idx] = b, wt[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}bool check(double mid)
{memset(dist, 0, sizeof dist);memset(st, 0, sizeof st);memset(cnt, 0, sizeof cnt);queue<int> q;for (int i = 1; i <= n; i ++ ) // 所有点存进队列{q.push(i);st[i] = true;}while (q.size()){int t = q.front();q.pop();st[t] = false;for (int i = h[t]; ~i; i = ne[i]){int j = e[i];if (dist[j] < dist[t] + wf[t] - mid * wt[i]){dist[j] = dist[t] + wf[t] - mid * wt[i]; // 更新最长距离cnt[j] = cnt[t] + 1;if (cnt[j] >= n) return true; // 更新次数超过n就说明有正环if (!st[j]){q.push(j);st[j] = true;}}}}return false;
}int main()
{cin >> n >> m;for (int i = 1; i <= n; i ++ ) cin >> wf[i]; // 记录点权memset(h, -1, sizeof h);for (int j = 0; j < m; j ++ ){int a, b, c;cin >> a >> b >> c;add(a, b, c);}double l = 0, r = 1e6;while (r - l > 1e-4) // 误差{double mid = (l + r) / 2;if (check(mid)) l = mid;else r = mid;}printf("%.2lf\n", l);
}
单词环
原题链接
我们有 n 个字符串,每个字符串都是由 a∼z 的小写英文字母组成的。
如果字符串 A 的结尾两个字符刚好与字符串 B 的开头两个字符相匹配,那么我们称 A 与 B 能够相连(注意:A 能与 B 相连不代表 B 能与 A 相连)。
我们希望从给定的字符串中找出一些,使得它们首尾相连形成一个环串(一个串首尾相连也算),我们想要使这个环串的平均长度最大。
如下例:
ababc
bckjaca
caahoynaab
第一个串能与第二个串相连,第二个串能与第三个串相连,第三个串能与第一个串相连,我们按照此顺序相连,便形成了一个环串,长度为 5+7+10=22(重复部分算两次),总共使用了 3 个串,所以平均长度是 223≈7.33。
输入格式
本题有多组数据。
每组数据的第一行,一个整数 n,表示字符串数量;
接下来 n 行,每行一个长度小于等于 1000 的字符串。
读入以 n=0 结束。
输出格式
若不存在环串,输出”No solution”,否则输出最长的环串的平均长度。
只要答案与标准答案的差不超过 0.01,就视为答案正确。
数据范围
1 ≤ n ≤ 105 1≤n≤105 1≤n≤105
输入样例
3
intercommunicational
alkylbenzenesulfonate
tetraiodophenolphthalein
0
输出样例
21.66
题意
n个字符串,如果a的末尾两个字符和b的开头相同则能相连,求能构成的环的平均长度最大值
思路
把每个字符串的首位两个字母看做一个点,比如说样例可以这样建图:
答案就变成了求 ∑ w i ∑ 1 \frac{\sum w_i}{\sum 1} ∑1∑wi的最大值
答案在(0, 1000)
之内,二分做,类似观光奶牛
最终判断式为: ∑ w i − M i d ∗ ∑ 1 > 0 \sum w_i - Mid*\sum 1>0 ∑wi−Mid∗∑1>0
判断有没有解直接把 Mid = 0
代入即可,因为如果等于0都不能满足的话大于0就更不会满足了
于是成功TLE,用一下玄学优化
代码
#include <bits/stdc++.h>using namespace std;const int N = 700, M = 100010;int n;
int h[N], e[M], ne[M], w[M], idx;
double dist[N];
int cnt[N];
bool st[N];void add(int a, int b, int c)
{e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}bool check(double mid)
{memset(st, 0, sizeof st);memset(cnt, 0, sizeof cnt);queue<int> q;for (int i = 0; i < 676; i ++ ) // 所有点存入队列{q.push(i);st[i] = true;}int count = 0;while (q.size()){int t = q.front();q.pop();st[t] = false;for (int i = h[t]; ~i; i = ne[i]){int j = e[i];if (dist[j] < dist[t] + w[i] - mid){dist[j] = dist[t] + w[i] - mid;cnt[j] = cnt[t] + 1;if (++ count > 10000) return true; // 次数过多直接返回(玄学可能失败if (cnt[j] >= N) return true; // 这个是保证一定正确的if (!st[j]){q.push(j);st[j] = true;}}}}return false;
}int main()
{char str[1010];while (scanf("%d", &n), n){memset(h, -1, sizeof h);idx = 0;for (int i = 0; i < n; i ++ ){cin >> str;int len = strlen(str);if (len >= 2){// 用类似于26进制的方法存储int left = (str[0] - 'a') * 26 + str[1] - 'a';int right = (str[len - 2] - 'a') * 26 + str[len - 1] - 'a';add(left, right, len);}}if (!check(0)) puts("No solution"); // 判断是否有解else{double l = 0, r = 1000;while (r - l > 1e-4) // 误差{double mid = (l + r) / 2;if (check(mid)) l = mid;else r = mid;}printf("%lf\n", r);}}
}
相关文章:
【图论】SPFA求负环
算法提高课笔记 文章目录 基础知识例题虫洞题意思路代码 观光奶牛题意思路代码 单词环题意思路代码 基础知识 负环:环上权值之和是负数 求负环的常用方法 基于SPFA 统计每个点入队次数,如果某个点入队n次,则说明存在负环(完全…...
vue3中的吸顶导航交互实现 | VueUse插件
目的:浏览器上下滚动时,若距离顶部的滚动距离大于78px,吸顶导航显示,小于78px隐藏。使用vueuse插件中的useScroll方法和动态类名控制进行实现 1. 安装 npm i vueuse/core 2. 获得滚动距离 项目中导入࿰…...
MySql 笔记
数据结构:BTREE 二叉树:顺序增长依次查询效率低 红黑树: 数据多了深度越深,效率自然低了 HASH: 查询条件限制 B-TREE:度(degree)-节段的数据存储个数,叶节点具有 相…...
部署elasticsearch集群
创建es集群 编写一个docker-compose.yaml文件,内容如下 version: 2.2 services:es01:image: elasticsearch:7.12.1container_name: es01environment:- node.namees01- cluster.namees-docker-cluster- discovery.seed_hostses02,es03- cluster.initial_master_nod…...
CTF入门学习笔记——Crypto密码(现代密码)
文章目录 CTF入门学习笔记——Crypto密码(现代密码)因数分解因数分解 共享素数Bigrsa 低加密指数攻击(小明文攻击)crypto5 共模攻击rsa_output 广播攻击Crazy_Rsa_Tech 待补充 CTF入门学习笔记——Crypto密码(现代密码…...
(3)MyBatis-Plus待开发
常用注解 TableName MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定即实体类型决定,且默认操作的表名和实体类型的类名一致,如果不一致则会因找不到表报异常 //向表中插入一条数据 Test public void testInsert(){User user new User(null, &…...
正则表达式参考手册
修饰符 修饰符用于执行区分大小写和全局匹配: 修饰符描述i执行对大小写不敏感的匹配。g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。m执行多行匹配。 方括号 方括号用于查找某个范围内的字符: 表达式描述[abc]查找方括号之间…...
【农业生产模拟】WOFOST模型与PCSE模型实践
查看原文>>>【农业生产模拟】WOFOST模型与PCSE模型实践 实现作物产量的准确估算对于农田生态系统响应全球变化、可持续发展、科学粮食政策制定、粮食安全维护都至关重要。传统的经验模型、光能利用率模型等估产模型原理简单,数据容易获取,但是…...
PHP8中获取并删除数组中最后一个元素-PHP8知识详解
在php8中,array_pop()函数将返回数组的最后一个元素,并且将该元素从数组中删除。语法格式如下: array_pop(目标数组) 获取并删除数组中最后一个元素,参考代码: <?php $stu array(s001>明明,s002>亮亮,s…...
JS原理-笔记(1/3)
JS原理-笔记(1/3) 知识点自测 今天课程中涉及到的已学习知识点 函数的call方法-文档链接 // 以指定的this调用函数,并通过 从第二个参数开始依次传递参数 function func(food,drink){console.log(this)console.log(food)console.log(drink)…...
Django创建应用、ORM的进阶使用及模型类数据库迁移
1 Django项目创建第一个应用 Django 项目就是基于 Django 框架开发的 Web 应用,它包含了一组配置和多个应用,我们把应用称之为 App,在前文中对它也做了相应的介绍,比如 auth、admin,它们都属于 APP。 一个 App 就是一…...
tcpdump 如何使用
tcpdump 是一个在Unix和类Unix系统上运行的网络抓包工具,它用于捕获网络流量并将其转储到文件中以供后续分析。tcpdump非常强大,可以用于监控、调试和分析网络通信,用于排查网络问题以及安全审计。以下是关于如何使用tcpdump的详细介绍&#…...
goweb入门
创建gomod项目 go mod init web01新建main.go package mainimport ("fmt""net/http" )func handler(writer http.ResponseWriter, request *http.Request) {fmt.Fprintf(writer, "Hello World,%s!", request.URL.Path[1:]) } func main() {fmt…...
【python爬虫】批量识别pdf中的英文,自动翻译成中文下
不管是上学还是上班,有时不可避免需要看英文文章,特别是在写毕业论文的时候。比较头疼的是把专业性很强的英文pdf文章翻译成中文。我记得我上学的时候,是一段一段复制,或者碰到不认识的单词就百度翻译一下,非常耗费时间。之前的文章提供了批量识别pdf中英文的方法,详见【…...
YApi 新版如何查看 http 请求数据
YApi 新版如何查看 http 请求数据 因chrome 安全策略限制,在 cross-request 升级到 3.0 后, 不再支持文件上传功能,并且需要通过以下方法查看 network:1.首先在chrome 输入 > chrome://extensions打开扩展页2.开启开发者模式3.点击 cross…...
自动驾驶(apollo)
💓博主csdn个人主页:小小unicorn 🚚代码仓库:小小unicorn的代码仓库🚚 🌹🌹🌹关注我带你学习编程知识 自动驾驶技术 引言自动驾驶的基本原理自动驾驶的技术挑战自动驾驶的潜在影响结…...
web3.0涉及的技术
非同质化代币 非同质化代币(Non-Fungible Tokens,NFTs)是一种数字资产,与传统的加密货币(如比特币或以太币)不同,它们具有独特性和不可替代性。NFTs 是基于区块链技术的数字资产,用…...
26. 不相同的字符串(第一期模拟笔试)
题目:样例: 输入 1 abab 输出 2 思路: 这里的题目要求我们要最少操作删除次数,我们可以先统计每个字符个数,然后开始删除,每操作删除一次,就会产生一个新字符,ans r[i] >> 1…...
Rethink LSTMGRU
LSTM 设计思想 姑且不看偏置。 W W W 和 U U U 是加权的矩阵,写模型的时候用 nn.Linear(in_dim, out_dim) 就成; σ \sigma σ 是 Sigmoid 函数 第一条,遗忘门,定义为 有多少内容需要被遗忘;第二条:输入门…...
状态管理艺术——借助Spring StateMachine驭服复杂应用逻辑
文章目录 1. 什么是状态2. 有限状态机概述3. Spring StateMachine4. Spring StateMachine 入门小案例4.1 接口测试 5. 总结 1. 什么是状态 在开发中,无时无刻离不开状态的一个概念,任何一条数据都有属于它的状态。 比如一个电商平台,一个订…...
获取和设置小程序和h5的页面栈
获取页面栈: 语法: let pages getCurrentPages(); 设置页面栈: 小程序语法: pages.data H5语法: pages let pages getCurrentPages(); let page pages[pages.length - 2]; if(page.route "pages/conf…...
Mysql基于成本选择索引
本篇文章介绍mysql基于成本选择索引的行为,解释为什么有时候明明可以走索引,但mysql却没有走索引的原因 mysql索引失效的场景大致有几种 不符合最左前缀原则在索引列上使用函数或隐式类型转换使用like查询,如 %xxx回表代价太大索引列区分度过…...
Element-ui container常见布局
1、header\main布局 <template> <div> <el-container> <el-header>Header</el-header> <el-main>Main</el-main> </el-container> </div> </template> <style> .el-header { …...
ssm实现折线统计图
方法1:单张数据表中的数据图表生成 图表统计,查看部门人数统计这里实现的时单张表中的数据实现部门人数折线统计图展示。 <script type"text/javascript">// 利用AjAx来获取后台传入的数据(Responsebody注解传入的&…...
GLSL ES着色器 精度限定字
目录 前言 WebGL支持的三种精度 数据类型的默认精度 float类型没有默认精度 预处理指令 在GLSL ES中常用的三种预处理指令。 预定义的内置宏 前言 GLSL ES新引入了精度限定字,目的是帮助着色器程序提高运行效率,削减内存开支。顾名思义…...
webrtc的FULL ICE和Lite ICE
1、ICE的模式 分为FULL ICE和Lite ICE: FULL ICE:是双方都要进行连通性检查,完成的走一遍流程。 Lite ICE: 在FULL ICE和Lite ICE互通时,只需要FULL ICE一方进行连通性检查, Lite一方只需回应response消息。这种模式对于部署在公网…...
flink的几种常见的执行模式
背景 在运行flink时,我们经常会有几种不同的执行模式,比如在IDE中启动时,通过提交到YARN上,还有通过Kebernates启动时,本文就来记录一下这几种模式 flink的几种执行模式 flink嵌入式模式: 这是一种我们在…...
蓝桥杯备赛Day8——队列
大家好,我是牛哥带你学代码,本专栏详细介绍了蓝桥杯备赛的指南,特别适合迎战python组的小白选手。专栏以天作为单位,定期更新,将会一直更新,直到所有数据结构相关知识及高阶用法全部囊括,欢迎大家订阅本专栏! 队列也属于基础数据结构。 队列概念 队列是一种数据结构,…...
用滑动条做调色板---cv2.getTrackbarPos(),cv2.creatTrackbar()
滑动轨迹栏作调色板 cv.createTrackbar(‘R’, ‘image’, 0, 255, nothing) 参数:哪个滑动轨迹栏,哪个窗口,最小值,最大值,回调函数 cv.getTrackbarPos(‘R’, ‘image’) 参数:轨迹栏名,窗口…...
dubbo 服务注册使用了内网IP,而服务调用需要使用公网IP进行调用
一、问题描述: 使用dubbo时,提供者注册时显示服务地址ip为[内网IP:20880],导致其他消费者在外部连接的情况下时,调用dubbo服务失败 二、解决办法 方法一、修改hosts文件 (1). 先查询一下服务器的hostna…...
wordpress缩略图不清晰怎么办/站长之家查询域名
Description 对家庭菜园有兴趣的JOI君每年在自家的田地中种植一种叫做IOI草的植物。JOI君的田地沿东西方向被划分为N个区域,由西到东标号为1~N。IOI草一共有N株,每个区域种植着一株。在第i个区域种植的IOI草,在春天的时候高度会生长至hi&…...
网站建设刂搜金手指下拉二五/磁力屋torrentkitty
学习Linux容易嘛?我说超容易,你肯定不信。那学习Linux最好的学习方法是什么,就是脑子里面一直提问题,不停的提,时时刻刻提,如果你没有问题,那再容易的学习书你也看不懂。 《超容易的Linux系统管…...
360免费建站方法/seo优化几个关键词
上一篇我们详细介绍了Predicate函数式接口中主要的一些方法使用,本篇介绍的Optional虽然并不是一个函数式接口,但是也是一个极其重要的类。Optional并不是我们之前介绍的一系列函数式接口,它是一个class,主要作用就是解决Java中的…...
wordpress php版本更改/深圳媒体网络推广有哪些
.parents()返回指定的祖先元素 .toFixed(2)让返回的数字保留两位小数...
wordpress标题图片代码/跨境电商平台
【题目】 将六个数字1,1,2,2,3,3排成一排,使得两个1之间有一个数字,两个2之间有两个数字,两个3之间有3个数字。 此题的解决并不困难,我们可以采用枚举法:…...
网站建设致谢/全网络品牌推广
我正在我的窗口上运行tomcat 7.0.47,并且我在与BlueHost存储的数据之间存在Mysql数据库连接.当我在本地运行它时,它会成功运行并且在没有任何错误的情况下对BlueHost数据库进行连接.但是当我尝试在运行tomcat 7.0.42的linux环境中部署其war文件,它给出了以下错误:or…...