刷题记录:牛客NC24858Job Hunt [最长路+两种不同判环详解]

news2024/10/2 1:30:31

传送门:牛客

题目描述:

奶牛们正在找工作。农场主约翰知道后,鼓励奶牛们四处碰碰运气。而且他还加了一条要求:一头牛在一个城市
最多只能赚D(1≤D≤1000)美元,然后它必须到另一座城市工作。当然,它可以在别处工作一阵子后又回到原
来的城市再最多赚D美元。而且这样的往返次数没有限制。
城市间有P(1≤P≤150)条单向路径连接,共有C(2≤C≤220)座城市,编号从1到C。奶牛贝茜当前处在城市S
(1≤S≤C)。路径i从城市A_i到城市B_i(1≤A_i≤C,1≤B_i≤C),在路径上行走不用任何花费。
为了帮助贝茜,约翰让它使用他的私人飞机服务。这项服务有F条(1≤F≤350)单向航线,每条航线是从城市J_i
飞到另一座城市K_i(1≤J_i≤C,1≤K_i≤C),费用是T_i(1≤T_i≤50000)美元。如果贝茜手中没有现钱,可以
用以后赚的钱来付机票钱。
贝茜可以选择在任何时候,在任何城市退休。如果在工作时间上不做限制,贝茜总共可以赚多少钱呢?如果赚的
钱也不会出现限制,就输出-1。
输入:
100 3 5 2 1
1 5
2 3
1 4
5 2 150
2 5 120
输出:
250

一道求最长路的题目,需要好好掌握
关于最长路:如果边权全是正数或者全是负数,可以使用 d i j k s t r a dijkstra dijkstra解决,但是如果边权有正有负,那么 d i j k s t r a dijkstra dijkstra将无法解决,此时只能寻求于 S p f a Spfa Spfa

主要思路:

  1. 首先我们观察一下题意,我们发现有两种路线,一种是没有路费的,一种是有路费的.并且我们到达一座城市就可以获得D,那么我们为什么不把我们的收获加入到我们的边权之中去呢.也就是如果不使用机票,我们经过这条边就可以获得D,如果使用机票,我们就可以获得D-Ti.那么这道题最终就转化成了一道跑最长路的问题,最终的答案就是图上最长的一段路径,并且显然的,我们这张图是有正有负的,所以并不能使用 d i j k s t r a dijkstra dijkstra进行,得使用 S p f a Spfa Spfa
  2. 对于无限钱的问题,那就是有一个正环存在了,因为有一个正环存在,那么我们显然可以在正环中无限循环,因为始终是正收入,所以我们还需要Spfa来判环

对于Spfa跑最长路的问题,网上博客讲的都很清楚,但是大多遇到判环问题都是一笔带过,但其实判环这一环节还是需要好好品味一下的,接下来就较为详细的介绍一下判环的依据


Spfa有两种判环的方式:

一种是判断以当前点结尾的最长路的边是否大于 n − 1 n-1 n1条,如果大于就是有环的存在
这种方法比较好理解,因为我们的点最多只有n个,那么对于我们的最长路来说,如果没有环的问题的话,我们的路径数最多肯定等于点数-1,也就是一条路直接过去(如果不理解,可以自己画一下)关于更新部分,也非常好理解,当前的点既然能被更新,那么就说明目前这种状态是最长路,那么显然边数应该由他之前的点的最长路边数递增过来

部分代码:

下面中的cnt记录的是边数
		for(int i=0;i<edge[u].size();i++) {
			int v=edge[u][i].v;
			if(dis[v]<dis[u]+edge[u][i].w) {
				dis[v]=dis[u]+edge[u][i].w;
				cnt[v]=cnt[u]+1;
				if(cnt[v]>c-1) return -1;
				if(!vis[v]) {
					q.push(v);
					vis[v]=1;
				}
			}
		}

另外一种是判断当前的点的更新次数是否大于n-1

这一种方法也是网上使用的较多的方式,这种方式主要是利用了BFS的性质.因为是Spfa的本质还是BFS.所以当Spfa中每次扩展一个点的时候.注意这个扩展指的是入队而不是松弛,有很多博客写的是松弛部分,这是错误的,因为我们在一次BFS中可能有多个相等数量边优化该点的操作,但是此时我们的BFS扩展的边数是相同的.类似于下面的4点
在这里插入图片描述

我们发现此时以该点为终点的最长路的边肯定是大于等于该点入队的次数的(因为即使我们每一个BFS多扩展一条边都更新了该点,该点入队的次数也不会大于边数),那么假设我们当前的点更新次数都比n-1大了,那就意味着我们的边数大于了n-1,那肯定存在环.

部分代码:

if(dis[u]+w<dis[v]){
	dis[v]=dis[u]+w;
	if(!vis[v]){
	if(++cnt[v]>=n)//注意就是这个位置的判断。一定要保证在判vis之后,即判入队次数;而不是在判vis之前,即判松弛次数!!!
	{
		printf("YES\n");return;
	}
	vis[v]=1;q.push(v);
	}
}

但是,第二种方法的空间复杂度显然比第一种要大,时间复杂度也比第一种要大,理由这里就不讲了,可以自行百度或者思考,所以强烈建议使用第一种方法,毕竟第一种方法既好用,又好理解,为什么不用呢??


下面是这道题的代码部分(使用第一种方法判环):

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
#include <deque>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
int d,p,c,f,s;
struct Node{
	int v,w;
};
vector<Node>edge[maxn];
int vis[maxn],cnt[maxn],dis[maxn];
int spfa(int S) {
	queue<int>q;
	for(int i=1;i<=c;i++) dis[i]=-inf;
	dis[S]=d;
	vis[S]=1;cnt[S]=0;
	q.push(S);
	while(!q.empty()) {
		int u=q.front();q.pop();
		vis[u]=0;
		for(int i=0;i<edge[u].size();i++) {
			int v=edge[u][i].v;
			if(dis[v]<dis[u]+edge[u][i].w) {
				dis[v]=dis[u]+edge[u][i].w;
				cnt[v]=cnt[u]+1;
				if(cnt[v]>c-1) return -1;
				if(!vis[v]) {
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
	return 1;
}
int main() {
	d=read(),p=read(),c=read(),f=read(),s=read();
	for(int i=1;i<=p;i++) {
		int u=read(),v=read();
		edge[u].push_back({v,d});
	}
	for(int i=1;i<=f;i++) {
		int u=read(),v=read(),w=read();
		edge[u].push_back({v,d-w});
	}
	if(spfa(s)==-1) printf("-1");
	else {
		int ans=-inf;
		for(int i=1;i<=c;i++) ans=max(ans,dis[i]);
		cout<<ans<<endl;
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/128035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2自由度陀螺仪滑模控制和PID控制跟踪目标轨迹

目录 前言 1.陀螺仪模型 2.滑模跟踪控制 3.PID控制 4.总结 前言 不为别的&#xff0c;这篇小文章只为内涵某人&#xff0c;问候一下他&#xff1a;不是有手就行&#xff0c;哈哈~ 1.陀螺仪模型 2.滑模跟踪控制 对于2自由度陀螺仪有两个方向x、y跟踪&#xff0c;所以需要…

对于软件测试认识的几大误区,看看你有没有?

对于软件开发来说&#xff0c;软件测试可能还不被大众了解&#xff0c;很多开发人员&#xff0c;包括很多软件高层管理人员&#xff0c;由于缺乏软件测试的知识和实践经验&#xff0c;对软件测试的认识还有很多的误区&#xff1a; 误区一&#xff1a;如果软件发布后有质量问题…

我们一起来谈谈高并发和分布式系统的幂等如何处理!

什么是幂等性 幂等是一个数学与计算机学概念&#xff0c;在数学中某一元运算为幂等时&#xff0c;其作用在任一元素两次后会和其作用一次的结果相同。 在计算机中编程中&#xff0c;一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。 幂等函数或幂等…

Codeforces Round #841 (Div. 2)

题目链接 A. Joey Takes Money 题目描述 input output 题意&#xff1a; 有一个长度为n的数组&#xff0c;你可以进行一步操作&#xff0c;选择两个i,j&#xff0c;然后再选择两个数x,y&#xff0c;使得a[i]a[j] xy&#xff0c;然后将a[i] x,a[j] y&#xff0c;问任意步操…

Spring 中运用的 9 种设计模式

Spring中涉及的设计模式总结&#xff0c;在面试中也会经常问道 Spring 中设计模式的问题。本文以实现方式、实质、实现原理的结构简单介绍 Sping 中应用的 9 种设计模型&#xff0c;具体详细的刨析会在后面的文章发布&#xff0c;话不多说&#xff0c;来个转发、在看、收藏三连…

京东软件测试岗:惨不忍睹的三面,幸好做足了准备,月薪17k,已拿offer

我今年25岁&#xff0c;专业是电子信息工程本科&#xff0c;19年年末的时候去面试&#xff0c;统一投了测试的岗位&#xff0c;软件硬件都有&#xff0c;那时候面试的两家公司都是做培训的&#xff0c;当初没啥钱&#xff0c;他们以面试为谎言再推荐去培训这点让我特别难受。 …

Unity 搭建ILRuntime开发环境

Unity热更新目前主流的方案有: Lua, ILRuntime, puerts, huatuo方案。前两个大家都比较熟悉了&#xff0c;puerts 是基于TypeScript开发的热更新&#xff0c;huatuo是基于C#的方案。后两个大家会比较陌生。本系列分享基于ILRuntime来做热更新。 对啦&#xff01;这里有个游戏开…

【财务】FMS财务管理系统---存货管理

前一篇文章介绍了付款相关的内容&#xff0c;本文中笔者继续介绍FMS财务管理系统的设计&#xff0c;今天是关于存货管理的介绍。 财务存货管理应该就是针对公司的生产原材料、物料、成品、加工品的数量与金额的管控。 在前面也介绍了&#xff0c;存货属于公司的资产&#xff0…

纯Java实现一个网页版的Xshell

前言 最近由于项目需求&#xff0c;项目中需要实现一个WebSSH连接终端的功能&#xff0c;由于自己第一次做这类型功能&#xff0c;所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用&#xff0c;当时看到了很多这方面的项目&#xff0c;例如&#xff1a;GateOne、webss…

微信小程序实现身份证识别-orc

项目中有一个识别身份证的需求&#xff0c;经过调研&#xff0c;最后决定使用微信小程序orc插件进行开发。 一:首先登录小程序公众平台。 1:进入设置> 第三方设置。 2:添加ocr插件。 3:添加完后&#xff0c;需要领取免费额度&#xff0c;100次/天。 https://fuwu.weixin…

SpringBoot+Vue实现后疫情时代下的旅游管理系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

Linux高级之日志管理

Linux高级之日志管理1.系统常用日志2.日志服务的稳定性3.自定义日志服务4.日志轮替5.内存日志1.系统常用日志 日志文件用于记录linux系统的各种运行信息的文件&#xff0c;相当于linux主机的日记&#xff0c;不同的日志文件记载了不同类型的信息,如Linux内核消息、用户登录事件…

React学习04-React_Ajax

写在前面 React本身只关注于界面&#xff0c;并不包含发送ajax请求的代码前端应用需要通过ajax请求与后台进行交互&#xff08;json数据&#xff09;React应用中需要集成第三方ajax库&#xff08;或自己封装&#xff09; 常用的ajax请求库 jQuery&#xff1a;比较重&#xf…

C|%输出各种类型的值总结

参考&#xff1a; C语音输出各种类型数据的方式 c语言中%s的用法 %d&#xff1a;十进制有符号整数 输出的数据范围是 signed int 的范围&#xff0c;即 0x80000000 ~ 0x7FFFFFFF&#xff08;-2147483648~2147483647&#xff09; %u&#xff1a;十进制无符号整数 输出范围0~0xF…

JVM-垃圾回收

1、GC分类 &#xff08;1&#xff09;部分收集&#xff08;Partial GC&#xff09; 新生代收集&#xff08;Minor GC/Young GC&#xff09;&#xff1a;只对新生代进行垃圾收集。&#xff08;读音[ˈmaɪnə(r)]&#xff09; 老年代收集&#xff08;Major GC/Old GC&#xff09…

基于SpringBoot+mybatis+mysql+html家具城进销存管理系统

基于SpringBootmybatismysqlhtml家具城进销存管理系统一、系统介绍二、功能展示1.用户登陆2.进货管理(货物管理员)3.退货管理&#xff08;货物管理员&#xff09;4.商品销售、商品销售退货(商品管理员)5.管理商品、商品类别、供应商、客户&#xff08;商品管理员&#xff09;6.…

DirtyPipe(CVE-2022-0847)漏洞分析

前言 CVE-2022-0847 DirtyPipe脏管道漏洞是Linux内核中的一个漏洞&#xff0c;该漏洞允许写只读文件&#xff0c;从而导致提权。 调试环境 ubuntu 20.04Linux-5.16.10qemu-system-x86_64 4.2.1 漏洞验证 首先创建一个只读文件foo.txt&#xff0c;并且正常情况下是无法修改…

微信小程序集成three.js--6.利用raycastor选择对象

1.实例演示 小程序集成Three.js&#xff0c;利用raycaster实现对象的2.源码 &#xff08;1&#xff09;引入库并声明变量 import * as THREE from ../../libs/three.weapp.js import {OrbitControls } from ../../jsm/controls/OrbitControls const app getApp()// 声明一个…

知识付费系统源码搭建流程讲解、代码分析

知识付费系统是现在多数教培机构优先考虑的线上教学系统&#xff0c;而很多机构自身有技术人员常驻&#xff0c;所以不需要再花费资金去直接购买搭建好的成品系统&#xff0c;转而直接购买源码后&#xff0c;自行搭建配置。 目前&#xff0c;知识付费系统是许多教培机构转型的首…

BOSS直聘自动投简历聊天机器人的实现过程

这两年疫情&#xff0c;公司业务越来越差&#xff0c;必须得准备后路了&#xff0c;每天睡前都会在直聘上打一遍招呼&#xff0c;一直到打哈欠有睡意为止...,这样持续了一周&#xff0c;发现很难坚持&#xff0c;身为一名资深蜘蛛侠&#xff0c;怎么能这样下去呢&#xff1f;于…