洛谷P3953 [NOIP 2017 提高组] 逛公园

洛谷题目传送门

题目背景

NOIP2017 D1T3

题目描述

策策同学特别喜欢逛公园。公园可以看成一张 N N N 个点 M M M 条边构成的有向图,且没有 自环和重边。其中 1 1 1 号点是公园的入口, N N N 号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。

策策每天都会去逛公园,他总是从 1 1 1 号点进去,从 N N N 号点出来。

策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果 1 1 1 号点 到 N N N 号点的最短路长为 d d d,那么策策只会喜欢长度不超过 d + K d + K d+K 的路线。

策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?

为避免输出过大,答案对 P P P 取模。

如果有无穷多条合法的路线,请输出 − 1 -1 1

输入格式

第一行包含一个整数 T T T, 代表数据组数。

接下来 T T T 组数据,对于每组数据: 第一行包含四个整数 N , M , K , P N,M,K,P N,M,K,P,每两个整数之间用一个空格隔开。

接下来 M M M 行,每行三个整数 a i , b i , c i a_i,b_i,c_i ai,bi,ci,代表编号为 a i , b i a_i,b_i ai,bi 的点之间有一条权值为 c i c_i ci 的有向边,每两个整数之间用一个空格隔开。

输出格式

输出文件包含 T T T 行,每行一个整数代表答案。

输入输出样例 #1

输入 #1

2
5 7 2 10
1 2 1
2 4 0
4 5 2
2 3 2
3 4 1
3 5 2
1 5 3
2 2 0 10
1 2 0
2 1 0

输出 #1

3
-1

说明/提示

【样例解释1】

对于第一组数据,最短路为 3 3 3 1 → 5 , 1 → 2 → 4 → 5 , 1 → 2 → 3 → 5 1\to 5, 1\to 2\to 4\to 5, 1\to 2\to 3\to 5 15,1245,1235 3 3 3 条合法路径。

【测试数据与约定】

对于不同的测试点,我们约定各种参数的规模不会超过如下

测试点编号 T T T N N N M M M K K K是否有 0 0 0
1 1 1 5 5 5 5 5 5 10 10 10 0 0 0
2 2 2 5 5 5 10 3 10^3 103 2 × 10 3 2\times 10^3 2×103 0 0 0
3 3 3 5 5 5 10 3 10^3 103 2 × 10 3 2\times 10^3 2×103 50 50 50
4 4 4 5 5 5 10 3 10^3 103 2 × 10 3 2\times 10^3 2×103 50 50 50
5 5 5 5 5 5 10 3 10^3 103 2 × 10 3 2\times 10^3 2×103 50 50 50
6 6 6 5 5 5 10 3 10^3 103 2 × 10 3 2\times 10^3 2×103 50 50 50
7 7 7 5 5 5 10 5 10^5 105 2 × 10 5 2\times 10^5 2×105 0 0 0
8 8 8 3 3 3 10 5 10^5 105 2 × 10 5 2\times 10^5 2×105 50 50 50
9 9 9 3 3 3 10 5 10^5 105 2 × 10 5 2\times 10^5 2×105 50 50 50
10 10 10 3 3 3 10 5 10^5 105 2 × 10 5 2\times 10^5 2×105 50 50 50

对于 100 % 100\% 100% 的数据, 1 ≤ P ≤ 10 9 1 \le P \le 10^9 1P109 1 ≤ a i , b i ≤ N 1 \le a_i,b_i \le N 1ai,biN 0 ≤ c i ≤ 1000 0 \le c_i \le 1000 0ci1000

数据保证:至少存在一条合法的路线。


  • 2019.8.30 增加了一组 hack 数据 by @skicean
  • 2022.7.21 增加了一组 hack 数据 by @djwj233

思路详解

最短路

首先由于它要求最短路径,由于害怕被卡,所以保险起见我们采用dijkstra求解最短路。

void dij(ll o){//dijkstra标准模板,o为起点memset(dis,0x3f,sizeof(dis));//记得赋初值!!!memset(vis,0,sizeof(vis));queue<ll>q;q.push(o);vis[o]=1;dis[o]=0;while(!q.empty()){ll u=q.front();q.pop();vis[u]=0;for(ll i=h[u];i;i=ne[i]){ll v=to[i];if(dis[v]>dis[u]+w[i]){dis[v]=dis[u]+w[i];if(!vis[v]){vis[v]=1;q.push(v);}}}}
}

深搜求解

我们最多有 k k k的相差,考虑依次枚举实际相差的 q q q(否则可能计算不完全),采用记忆化深搜求解。具体步骤如下:

  1. 定义:记忆化数组 f u , j f_{u,j} fu,j为到 u u u点, q q q剩下 j j j的方案数。 d f s ( u , q ) dfs(u,q) dfs(u,q)同理
  2. 边界条件: f n , 0 = 1 f_{n,0}=1 fn,0=1
  3. 状态转移:令 d = q − ( d i s u + w i − d i s v ) d=q-(dis_{u}+w_{i}-dis_{v}) d=q(disu+widisv)即消耗了当前的 q q q后的值,若 d < 0 d<0 d<0则直接退出。
    否则累加答案: f u , j + = d f s ( v , d ) f_{u,j}+=dfs(v,d) fu,j+=dfs(v,d)

但是,我们发现,题目中说可能有无数解的情况,肯定是有0环,那如何判断是否有0环呢?,考虑定于数组 v i u , q vi_{u,q} viu,q,表示是否访问过状态 u , q {u,q} u,q,若在深搜访问状态 u , q {u,q} u,q v i u , q = = 1 vi_{u,q}==1 viu,q==1,那说明跑了一圈跑回来了,那一定有0环,标记并退出。

**int f[N][56],fl=0,vi[N][56];
int dfs(int u,int q){if(vi[u][q]){//已经访问过这种状态,有0环fl=1;return 0;}if(f[u][q]!=-1)return f[u][q];//记忆化深搜vi[u][q]=1;//标记f[u][q]=0;//由于f数组初始值为-1,将其赋值为0for(int i=h[u];i;i=ne[i]){int v=to[i];int d=q-(dis[u]+w[i]-dis[v]);//消耗后的状态if(d<0)continue;f[u][q]=(f[u][q]+dfs(v,d))%p;//求和,记得取模if(fl==1)return 0;//dfs(v,d)中fl变成了1也要退出}if(u==n&&q==0)f[u][q]=1;//边界vi[u][q]=0;//回溯return f[u][q];
}**

反向跑图

我们将代码提交上去,发现有些数据是错的。而且错误数据都是错误输出-1,即0环判断错误。这是为何?我们发现,如果一旦有0环我们的深搜便会返回-1,但其实有可能根本不会经过这个0环,那如何规避这个错误呢?我们直接反向跑图,这样乱跑的情况就会被规避掉。但要注意,状态转移变为了: d = q − ( d i s v + w i − d i s u ) d=q-(dis_{v}+w_{i}-dis_{u}) d=q(disv+widisu),因为原来是 v − > u v->u v>u,现在变为了 u − > v u->v u>v

完整代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2e5+4;
ll n,m,t,k,p;
ll h[N],to[N],w[N],ne[N],tot;
void add(ll u,ll v,ll d){tot++;to[tot]=v;w[tot]=d;ne[tot]=h[u];h[u]=tot;
}
struct edge{ll x,y,z;
}a[N];
ll dis[N],vis[N];
void dij(ll o){//dijkstra标准模板,o为起点memset(dis,0x3f,sizeof(dis));//记得赋初值!!!memset(vis,0,sizeof(vis));queue<ll>q;q.push(o);vis[o]=1;dis[o]=0;while(!q.empty()){ll u=q.front();q.pop();vis[u]=0;for(ll i=h[u];i;i=ne[i]){ll v=to[i];if(dis[v]>dis[u]+w[i]){dis[v]=dis[u]+w[i];if(!vis[v]){vis[v]=1;q.push(v);}}}}
}
ll ans;
ll f[N][56],fl=0,vi[N][56];
ll dfs(ll u,ll q){if(vi[u][q]){//已经访问过这种状态,有0环fl=1;return 0;}if(f[u][q]!=-1)return f[u][q];//记忆化深搜vi[u][q]=1;//标记f[u][q]=0;//由于f数组初始值为-1,将其赋值为0for(ll i=h[u];i;i=ne[i]){ll v=to[i];ll d=q-(dis[v]+w[i]-dis[u]);//消耗后的状态if(d<0)continue;f[u][q]=(f[u][q]+dfs(v,d))%p;//求和,记得取模if(fl==1)return 0;//dfs(v,d)中fl变成了1也要退出}if(u==1&&q==0)f[u][q]=1;//边界vi[u][q]=0;//回溯return f[u][q];
}
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>t;for(ll cas=1;cas<=t;cas++){cin>>n>>m>>k>>p;fl=0;tot=0;//链式前向星清空只需要清空tot与hmemset(h,0,sizeof(h));for(ll i=1;i<=m;i++){ll x,y,z;cin>>x>>y>>z;a[i]={x,y,z};//将边保存下来}for(ll i=1;i<=m;i++){ll x=a[i].x,y=a[i].y,z=a[i].z;add(x,y,z);//正向建边}dij(1);//正向跑最短路ans=0;tot=0;//清空memset(h,0,sizeof(h));for(ll i=1;i<=m;i++){//方向见图ll x=a[i].x,y=a[i].y,z=a[i].z;add(y,x,z);}memset(f,-1,sizeof(f));memset(vi,0,sizeof(vi));for(ll i=0;i<=k;i++){ans=(ans+dfs(n,i))%p;if(fl)break;}if(fl)cout<<-1<<'\n';else cout<<ans<<'\n';}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3+TypeScript+Element Plus 表格展开行优化方案

在 Vue3 TypeScript Element Plus 项目中优化表格展开行的内存使用&#xff0c;主要从 渲染优化、数据管理 和 内存回收 三方面入手。以下是最佳实践和完整解决方案&#xff1a; 1. 懒加载展开内容&#xff08;核心优化&#xff09; 只当行展开时才渲染内容&#xff0c;避免…

OpenCV——直方图与匹配

直方图与匹配 一、直方图简介二、直方图统计三、直方图比较四、直方图均衡化五、自适应的直方图均衡化六、直方图反向投影七、模板匹配 一、直方图简介 图像直方图&#xff08;Histogram&#xff09;是一种频率分布图&#xff0c;它描述了不同强度值在图像中出现的频率。图像直…

通义大模型在文档自动化处理中的高效部署指南(OCR集成与批量处理优化)

1. 传统OCR解决方案常面临识别精度低、版面分析能力弱、处理效率瓶颈等问题。通义大模型凭借其多模态理解和生成能力&#xff0c;为文档处理领域带来革命性突破。本文将深入探讨如何高效部署通义大模型实现端到端的文档自动化处理&#xff0c;特别聚焦OCR集成与批量处理优化两…

Ubuntu20.04通过ssh协议配置远程终端

一、在目标计算机&#xff08;即被连接的计算机&#xff09;上操作&#xff1a; 1、安装 OpenSSH 服务器&#xff1a; sudo apt update sudo apt install openssh-server3、启动并设置 SSH 服务开机自启&#xff1a; sudo systemctl enable --now ssh二、在源计算机&#xf…

《HTTP权威指南》 第7章 缓存

带着问题学习&#xff1a; 缓存如何提高性能如何衡量缓存的有效性缓存置于何处作用最大HTTP如何保持缓存副本的新鲜度缓存如何与其他缓存及服务器通信 web缓存是可以自动保存常见文档副本的HTTP设备。 缓存优点 减少冗余的数据传输&#xff0c;节省网络费用缓解网络瓶颈问题&…

第十三章 模板

函数模板 函数模板使用 函数模板注意事项 自动类型推导&#xff0c;必须推导出一致的数据类型T,才可以使用 模板必须要确定出T的数据类型&#xff0c;才可以使用 普通函数和函数模板的类型转化 普通函数隐式类型转化&#xff08;char转int&#xff09; 函数模板正常使用不会发生…

云计算-专有网络VPC

&#x1f310; 什么是 VPC&#xff1f;&#xff08;Virtual Private Cloud&#xff09; VPC&#xff08;Virtual Private Cloud&#xff0c;虚拟私有云&#xff09; 是公有云服务商提供的一种网络隔离服务&#xff0c;允许用户在云中创建一个逻辑隔离的私有网络环境。你可以在这…

关于*gin.Context的理解

关于*gin.Context的理解 作为初学者&#xff0c;在学习go语言用gin开发web时&#xff0c;我对*gin.Context感到困惑。本文章以自我总结为主&#xff0c;大部分为来自询问ai后的总结&#xff0c;如有问题欢迎指出。 *gin.Context可以理解为一个gin框架的上下文对象指针&#x…

Qt中的OpenGL (6)[坐标系统]

文章目录 文章说明学习目标目录结构坐标系统局部空间世界空间观察空间裁剪空间正射投影矩阵透视投影矩阵组合进入3D世界顶点数据着色器设置数据矩阵设置文章说明 本文是学习OpenGL的笔记,主要参考大神JoeyDeVries的LearnOpenGL第八课《坐标系统》,并将教程中的代码基于Qt进行…

Spring Aop @After (后置通知)的使用场景?

核心定义 After 是 Spring AOP 中的另一种通知&#xff08;Advice&#xff09;类型&#xff0c;通常被称为“后置通知”或“最终通知”。 它的核心作用是&#xff1a; 无论目标方法是正常执行完成&#xff0c;还是在执行过程中抛出了异常&#xff0c;After 通知中的代码 总是…

UNet改进(4):交叉注意力(Cross Attention)-多模态/多特征交互

在计算机视觉领域&#xff0c;UNet因其优异的性能在图像分割任务中广受欢迎。本文将介绍一种改进的UNet架构——UNetWithCrossAttention&#xff0c;它通过引入交叉注意力机制来增强模型的特征融合能力。 1. 交叉注意力机制 交叉注意力(Cross Attention)是一种让模型能够动态地…

C#里从CSV文件加载BLOB数据字段到数据库的处理

大量的数据保存在CSV文件, 当需要把这些数据加载到数据库,然后使用数据库来共享出去。 就需要把CSV文件导入数据库, 怎么样快速地把CSV文件导入数据库呢? 这个就需要使用类MySqlBulkLoader,它是mariadb数据库快速导入的方式。 一般使用SQL语句导入是10秒,那么使用这种方…

【后端】负载均衡

长期不定期更新补充。 定义 负载均衡&#xff08;Load Balancing&#xff09;是指将来自客户端的请求合理分发到多个服务器或服务节点&#xff0c;以提高系统性能、可用性与可靠性。 分工 前端不做负载均衡&#xff0c;前端只发请求&#xff0c;不知道请求去哪台服务器。 负…

记录一次:Java Web 项目 CSS 样式/图片丢失问题:一次深度排查与根源分析

记录一次&#xff1a;Java Web 项目 CSS 样式/图片丢失问题&#xff1a;一次深度排查与根源分析 **记录一次&#xff1a;Java Web 项目 CSS 样式丢失问题&#xff1a;一次深度排查与根源分析****第一层分析&#xff1a;资源路径问题****第二层分析&#xff1a;服务端跳转逻辑**…

torchmd-net开源程序是训练神经网络潜力

​一、软件介绍 文末提供程序和源码下载 TorchMD-NET 提供最先进的神经网络电位 &#xff08;NNP&#xff09; 和训练它们的机制。如果有多个 NNP&#xff0c;它可提供高效、快速的实现&#xff0c;并且它集成在 GPU 加速的分子动力学代码中&#xff0c;如 ACEMD、OpenMM 和 …

在Docker上安装Mongo及Redis-NOSQL数据库

应用环境 Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64) Docker version 28.1.1, build 4eba377 文章目录 一、部署Mongo1. 拉取容器镜像2. 生成Run脚本2.1 准备条件2.2 参数解读2.3 实例脚本 3. 实例操作3.1 Mongo bash控制台3.2 库表操作 4. MongoDB Compass (G…

Java 编程之责任链模式

一、什么是责任链模式&#xff1f; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 是一种行为型设计模式&#xff0c;它让多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;沿着这条…

1、做中学 | 一年级上期 Golang简介和安装环境

一、什么是golang Golang&#xff0c;通常简称 Go&#xff0c;是由 Google 公司的 Robert Griesemer、Rob Pike 和 Ken Thompson 于 2007 年创建的一种开源编程语言&#xff0c;并在 2009 年正式对外公布。 已经有了很多编程语言&#xff0c;为什么还要创建一种新的编程语言&…

Linux--迷宫探秘:从路径解析到存储哲学

上一篇博客我们说完了文件系统在硬件层面的意义&#xff0c;今天我们来说说文件系统在软件层是怎么管理的。 Linux--深入EXT2文件系统&#xff1a;数据是如何被组织、存储与访问的&#xff1f;-CSDN博客 &#x1f30c; 引言&#xff1a;文件系统的宇宙观 "在Linux的宇宙中…

淘宝商品数据实时获取方案|API 接口开发与安全接入

在电商数据获取领域&#xff0c;除了官方 API&#xff0c;第三方数据 API 接入也是高效获取淘宝商品数据的重要途径。第三方数据 API 凭借丰富的功能、灵活的服务&#xff0c;为企业和开发者提供了多样化的数据解决方案。本文将聚焦第三方数据 API 接入&#xff0c;详细介绍其优…