Luogu P3953 逛公园(最短路+记忆化搜索)
题面
题目描述
策策同学特别喜欢逛公园。公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边。其中 \(1\) 号点是公园的入口,\(N\) 号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。
策策每天都会去逛公园,他总是从 \(1\) 号点进去,从 \(N\) 号点出来。
策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果 \(1\) 号点到 \(N\) 号点的最短路长为 \(d\) ,那么策策只会喜欢长度不超过 \(d + K\) 的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?
为避免输出过大,答案对 \(P\) 取模。
如果有无穷多条合法的路线,请输出 \(-1\) 。
输入输出格式
输入格式:
第一行包含一个整数 \(T\) ,代表数据组数。
接下来 \(T\) 组数据,对于每组数据: 第一行包含四个整数 \(N,M,K,P\) ,每两个整数之间用一个空格隔开。
接下来 \(M\) 行,每行三个整数 \(a_i,b_i,c_i\) ,代表编号为 \(a_i,b_i\) 的点之间有一条权值为 \(c_i\) 的有向边,每两个整数之间用一个空格隔开。
输出格式:
输出文件包含 \(T\) 行,每行一个整数代表答案。
输入输出样例
输入样例:
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
输出样例:
3
-1
说明
【样例解释1】
对于第一组数据,最短路为 \(3\) 。 \(1 - 5, 1 - 2 - 4 - 5, 1 - 2 - 3 - 5\) 为 \(3\) 条合法路径。
【测试数据与约定】
对于不同的测试点,我们约定各种参数的规模不会超过如下
| 测试点编号 | \(T\) | \(N\) | \(M\) | \(K\) | 是否有 \(0\) 边 |
|---|---|---|---|---|---|
| \(1\) | \(5\) | \(5\) | \(10\) | \(0\) | 否 |
| \(2\) | \(5\) | \(1000\) | \(2000\) | \(0\) | 否 |
| \(3\) | \(5\) | \(1000\) | \(2000\) | \(50\) | 否 |
| \(4\) | \(5\) | \(1000\) | \(2000\) | \(50\) | 否 |
| \(5\) | \(5\) | \(1000\) | \(2000\) | \(50\) | 否 |
| \(6\) | \(5\) | \(1000\) | \(2000\) | \(50\) | 是 |
| \(7\) | \(5\) | \(100000\) | \(200000\) | \(0\) | 否 |
| \(8\) | \(3\) | \(100000\) | \(200000\) | \(50\) | 否 |
| \(9\) | \(3\) | \(100000\) | \(200000\) | \(50\) | 是 |
| \(10\) | \(3\) | \(100000\) | \(200000\) | \(50\) | 是 |
对于 $100 % $ 的数据, \(1 \le P \le 10^9,1 \le a_i,b_i \le N ,0 \le c_i \le 1000\) 。
数据保证:至少存在一条合法的路线。
思路
\(NOIP2017 / DAY1 / T3\)
首先我们求出每个点到 \(n\) 结点(公园出口)的距离,然后定义一个变量 \(dp[i][j]\) 表示比从 \(i\) 点出发到达 \(n\) 点的最短路长小于等于 \(j\) 的路径有多少条。然后我们逐步向后遍历整张图,求出的 \(dp[1][K]\) 就是题目要求的答案。遍历过程中我们可以用记忆化搜索的形式来优化时间复杂度。
那怎么判断无数多条合法情况呢?再定义一个变量 \(in[i][j]\) 表示在当前遍历过程中我们是否有在求 \(dp[i][j]\) 。如果有,说明搜索成环,直接返回 \(-1\) 。
具体实现代码如下:
LL dfs(LL now,LL k)
{
if(in[now][k]) return -1;//成环
if(dp[now][k]) return dp[now][k];//记忆化搜索
in[now][k]=true,dp[now][k]=0;//开始搜索
if(now==n) dp[now][k]=1;//搜到结尾时为一种情况
for(LL i=top[now];i;i=nex[i])
{
LL delta=dis[to[i]]-dis[now]+len[i];//与最短路之间的差距
if(delta<=k)
{
LL tmp=dfs(to[i],k-delta);
if(tmp==-1) return -1;//成环
dp[now][k]=(dp[now][k]+tmp)%p;
}
}
in[now][k]=false;//结束搜索
return dp[now][k];
}
函数调用入口就是:
printf("%lld\n",dfs(1,K));
怨念--;
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=100005;
LL T,n,m,K,p,dp[MAXN][55],dis[MAXN];
LL cnt,top[MAXN],to[MAXN<<1],len[MAXN<<1],nex[MAXN<<1];
LL __cnt,__top[MAXN],__to[MAXN<<1],__len[MAXN<<1],__nex[MAXN<<1];
bool vis[MAXN],in[MAXN][55];
LL read()
{
LL re=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
void SPFA()
{
memset(dis,0x3f,sizeof dis);
memset(vis,false,sizeof vis);
dis[n]=0;
queue<LL>Q;
Q.push(n);
while(!Q.empty())
{
LL now=Q.front();Q.pop();
vis[now]=false;
for(LL i=__top[now];i;i=__nex[i])
if(dis[__to[i]]>dis[now]+__len[i])
{
dis[__to[i]]=dis[now]+__len[i];
if(!vis[__to[i]])
{
vis[__to[i]]=true;
Q.push(__to[i]);
}
}
}
}
LL dfs(LL now,LL k)
{
if(in[now][k]) return -1;
if(dp[now][k]) return dp[now][k];
in[now][k]=true,dp[now][k]=0;
if(now==n) dp[now][k]=1;
for(LL i=top[now];i;i=nex[i])
{
LL delta=dis[to[i]]-dis[now]+len[i];
if(delta<=k)
{
LL tmp=dfs(to[i],k-delta);
if(tmp==-1) return -1;
dp[now][k]=(dp[now][k]+tmp)%p;
}
}
in[now][k]=false;
return dp[now][k];
}
int main()
{
T=read();
while(T--)
{
n=read(),m=read(),K=read(),p=read(),cnt=__cnt=0;
memset(dp,0,sizeof dp);
memset(top,0,sizeof top);
memset(__top,0,sizeof __top);
memset(in,false,sizeof in);
while(m--)
{
LL x=read(),y=read(),z=read();
to[++cnt]=y,len[cnt]=z,nex[cnt]=top[x],top[x]=cnt;
__to[++__cnt]=x,__len[__cnt]=z,__nex[__cnt]=__top[y],__top[y]=__cnt;
}
SPFA();
printf("%lld\n",dfs(1,K));
}
return 0;
}
Luogu P3953 逛公园(最短路+记忆化搜索)的更多相关文章
- [Luogu P3953] 逛公园 (最短路+拓扑排序+DP)
题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易 ...
- 逛公园 [NOIP2017 D1T3] [记忆化搜索]
Description 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的 ...
- luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)
先跑一边dijkstra算出从1到i的最短距离dis[i] 然后建反向边 从n开始记忆化搜索,(p,k)表示1到p的距离=dis[p]+k的方案数 答案就是$\sum\limits_{i=0}^{k} ...
- 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】
spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ...
- 【luogu P3953 逛公园】 题解
题目链接:https://www.luogu.org/problemnew/show/P3953 题外话:感觉2017年神题好多..这还不是最神的一道,真在考场上我也就写个最短路计数暴力了.现在在大佬 ...
- UVA - 10917 - Walk Through the Forest(最短路+记忆化搜索)
Problem UVA - 10917 - Walk Through the Forest Time Limit: 3000 mSec Problem Description Jimmy exp ...
- HDU 1142 A Walk Through the Forest(最短路+记忆化搜索)
A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...
- hdu 1428(很好的一道题,最短路+记忆化搜索)
漫步校园 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- Luogu P2149 [SDOI2009]Elaxia的路线(最短路+记忆化搜索)
P2149 [SDOI2009]Elaxia的路线 题意 题目描述 最近,\(Elaxia\)和\(w**\)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们必须合理地安排两个人在一起的 ...
随机推荐
- Python3简介
Python3简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有 ...
- selenium基础(窗口截图)
窗口截图 目的:当脚本执行出错时对当前窗口进行截图 方法:get_screenshot_as_file() #打开百度首页,搜索“selenium",完成后进行截图,并将结果保存至D:/te ...
- netty 私有协议栈
通信协议从广义上区分,可以分为公有协议和私有协议.由于私有协议的灵活性,它往往会在某个公司或者组织内部使用,按需定制,也因为如此,升级起来会非常方便,灵活性好.绝大多数的私有协议传输层都基于TCP/I ...
- 宽域POST提交数据
小数据宽域可以使用jsonp,但是大数据跨域必须post那么有以下2种方式 1,传统方式 动态生成form var url = ''var $iframe = $("<iframe s ...
- uoj60 怎样提高智商
题意:你需要构造n个四项选择题.格式为:问在前i个问题中选了几个hi字母? 输出有最多正确答案的构造方案. 标程: #include<cstdio> using namespace std ...
- AutoIt自动化编程(3)【转】
模拟鼠标点击(按钮等)控件 既然是模拟用户操作,自然就包括了模拟鼠标点击在内. 适用命令/函数:Click/MouseClick/ControlClick 其中Click/MouseClick用来模拟 ...
- windows 可执行文件分析
windows可执行文件是什么? 是具有PE文件格特性的文件,例如:.exe.dll.ocx等文件. 注:(这里只是让大家能明了一些,其实,可执行与否,和后缀没有什么关系,后缀只是windows方便管 ...
- 移动端开发框架Zepto.js
一.概述 Zepto.js是一个轻量的js库,它与jQuery有类似的API. zepto的设计目的是不到10K的通用库,快速下载,有一个熟悉的api-->精力专注在开发上. 流行起来的原因:轻 ...
- vue alert插件(标题为图片)(自写)
<template> <div class="modelSelf"> <div class="model" @click=&quo ...
- PHP面向对象访问修饰符的基本了解
l 文档的介绍: 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的.被定义为公有的类成员可以在任何地方被访问.被定义 ...