逛公园「NOIP2017」最短路+DP
大家好我叫蒟蒻,这是我的第一篇信竞题解blog
【题目描述】
策策同学特别喜欢逛公园。 公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边。其中 \(1\) 号点是公园的入口, \(N\) 号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。
策策每天都会去逛公园,他总是从 \(1\) 号点进去,从 \(N\) 号点出来。
策策喜欢新鲜的事物,他不希望有两天逛公园的路线完全一样,同时策策还是一个特别热爱学习的好孩子,他不希望每天在逛公园这件事上花费太多的时间。如果 \(1\) 号点到 \(N\) 号点的最短路长为 \(d\),那么策策只会喜欢长度不超过 \(d + K\) 的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮他吗?
为避免输出过大,答案对 \(P\) 取模。
如果有无穷多条合法的路线,请输出 \(−1\)。
【输入格式】
第一行包含一个整数 \(T\), 代表数据组数。
接下来 \(T\) 组数据,对于每组数据:
第一行包含四个整数 \(N,M,K,PN,M,K,P\), 每两个整数之间用一个空格隔开。
接下来 \(m\) 行,每行三个整数 \(a_i,b_i,c_i\), 代表编号为 \(a_i,b_i\) 的点之间有一条权值为 \(c_i\) 的有向边,每两个整数之间用一个空格隔开。
【输出格式】
输出文件包含 \(T\) 行,每行一个整数代表答案。
【思路点拨】
是个人应该都能看出此题是要先求出最短路.jpg
亲测此题SPFA跑的比Dijkstra快
为什么?我人品好
最短路只能求出路径长度,计算路径条数似乎做不到——
然后就gg了
据说NOIP2017 Day1三题都没有DP 作为Day2压轴题 DP是压轴出场
What is DP? Is that Dui Pai?
考虑DP的子状态 肯定有一维是要存储当前的点编号
注意到此题 \(k \le 50\) 第二维可以存储当前路径1-i的长度超出了1-i最短路多少
于是 \(dp[i][j]\) 就表示\(1-i\)路径长度为 \(dis[i]\) (\(1-i\)最短路) \(+ j\) 的方案数
对于任意一个 \(u\), 设它有一条路径连向 \(v\)。
则可以推出 \(dp[u][l] = \sum dp[v][dis[u]-dis[v]+l-edge(u, v)] (1 \le l \le k)\)
然后就可以开始快乐DP了
如何判断 \(0\) 环?
dfs的时候记录一下就行了
要记得加记忆化搜索
贴心提示
日常全开\(long long\)是好习惯 多卡常 出奇迹
【代码实现】
#include <bits/stdc++.h>
#define ri register long long
using namespace std;
typedef long long ll;
ll t, n, m, k, p, ans;
ll head[200005], pre[800005], to[800005], val[800005], len;
ll head2[200005], pre2[800005], to2[800005], val2[800005], len2;
ll dis[200005], dis2[200005], visit[200005][61];
ll dp[200005][61];//又到了我们最喜欢的DP时间
bool vis[200005], ok;
inline ll read() {
ll ret = 0, flag = 1;
char ch = getchar();
while (ch > '9' || ch < '0') {
if (ch == '-') flag = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ret = (ret << 1) + (ret << 3) + (ch ^ '0');
ch = getchar();
}
return ret * flag;
}
inline void write(ll num) {
if (num > 9) write(num / 10);
putchar(num % 10 + '0');
}
inline void insert(ll u, ll v, ll w) {
pre[++len] = head[u]; head[u] = len;
to[len] = v; val[len] = w;
}
inline void insert2(ll u, ll v, ll w) {
pre2[++len2] = head2[u]; head2[u] = len2;
to2[len2] = v; val2[len2] = w;
}
inline void add(ll &a, ll b) { //究极玄学卡常
a += b;
if (a > p) {
a -= p;
}
}
inline void SPFA() {
vis[1] = 1;
dis[1] = 0;
queue<ll> q;
q.push(1);
while (!q.empty()) {
ll x = q.front();
q.pop();
for (ri i = head[x]; i != 0; i = pre[i]) {
ll y = to[i];
if (dis[y] > dis[x] + val[i]) {
dis[y] = dis[x] + val[i];
if (!vis[y]) {
vis[y] = 1;
q.push(y);
}
}
}
vis[x] = 0;
}
}
ll dfs(ll c, ll nowk) {
if (dp[c][nowk] != -1) return dp[c][nowk];
visit[c][nowk] = 1;
dp[c][nowk] = 0;
for (ri i = head2[c]; i; i = pre2[i]) {
ll next = dis[c] - dis[to2[i]] + nowk - val2[i];
if (next < 0) continue;
if (visit[to2[i]][next]) {
ok = 1;
}
add(dp[c][nowk], dfs(to2[i], next));
}
visit[c][nowk] = 0;
return dp[c][nowk];
}
void This_is_a_dp() {
dp[1][0] = 1;
for (ri i = 0; i <= k; i++) {
add(ans, dfs(n, i));
}
}
int main() {
t = read();
while (t--) {
memset(head, 0, sizeof(head));
memset(head2, 0, sizeof(head2));
memset(dp, -1, sizeof(dp));
memset(visit, 0, sizeof(visit));
memset(vis, 0, sizeof(vis));
memset(dis, 0x7f, sizeof(dis));
ok = 0;
len = ans = len2 = 0;
n = read();
m = read();
k = read();
p = read();
for (ri i = 1; i <= m; i++) {
ll u, v, w;
u = read();
v = read();
w = read();
insert(u, v, w);
insert2(v, u, w);
}
SPFA();
/*DP!*/
This_is_a_dp();
dfs(n, k + 1);
if (ok) {
puts("-1");
continue;
}
write(ans); puts("");
}
return 0;
}
时间复杂度 \(O((k+x)m)\) \((x\)为\(SPFA\)玄学次数\()\)
逛公园「NOIP2017」最短路+DP的更多相关文章
- 「NOIP2017」宝藏
「NOIP2017」宝藏 题解 博客阅读效果更佳 又到了一年一度NOIPCSP-S 赛前复习做真题的时间 于是就遇上了这道题 首先观察数据范围 \(1 \le n \le 12\) ,那么极大可能性是 ...
- 「luogu4366」最短路
「luogu4366」最短路 传送门 直接连边显然不行,考虑优化. 根据异或的结合律和交换律等优秀性质,我们每次只让当前点向只有一位之别的另一个点连边,然后就直接跑最短路. 注意点数会很多,所以用配对 ...
- NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】
题目描述 策策同学特别喜欢逛公园.公园可以看成一张NNN个点MMM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NNN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花 ...
- NOIP 2017 逛公园 记忆化搜索 最短路 好题
题目描述: 策策同学特别喜欢逛公园.公园可以看成一张N个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. ...
- LOJ2316. 「NOIP2017」逛公园【DP】【最短路】【思维】
LINK 思路 因为我想到的根本不是网上的普遍做法 所以常数出奇的大,而且做法极其暴力 可以形容是带优化的大模拟 进入正题: 首先一个很显然的思路是如果在合法的路径网络里面存在零环是有无数组解的 然后 ...
- 【LOJ2316】「NOIP2017」逛公园
[题目链接] [点击打开链接] [题目概括] 对给定\(K\),起点\(1\)到终点\(n\)中对长度为\([L,L+K]\)的路径计数. \(L\)为\(1\)到\(n\)的最短路长度. [思路要点 ...
- 「NOIP2017」逛公园
传送门 Luogu 解题思路 考虑 \(\text{DP}\). 设 \(f[u][k]\) 表示从 \(u\) 到 \(n\) 走过不超过 \(Mindis(u, n) + k\) 距离的方案数. ...
- loj2314 「NOIP2017」小凯的疑惑[同余最短路or数论]
这题以前就被灌输了“打表找规律”的思想,所以一直没有好好想这道题,过了一年还不太会qwq.虽然好像确实很简单,但是还是带着感觉会被嘲讽的心态写这个题解...而且还有一个log做法不会... 法1:(一 ...
- loj2318 「NOIP2017」宝藏[状压DP]
附带其他做法参考:随机化(模拟退火.爬山等等等)配合搜索剪枝食用. 首先题意相当于在图上找一颗生成树并确定根,使得每个点与父亲的连边的权乘以各自深度的总和最小.即$\sum\limits_{i}dep ...
随机推荐
- [AI开发]目标跟踪之速度计算
基于视频结构化的应用中,目标在经过跟踪算法后,会得到一个唯一标识和它对应的运动轨迹,利用这两个数据我们可以做一些后续工作:测速(交通类应用场景).计数(交通类应用场景.安防类应用场景)以及行为检测(交 ...
- netty实现的RPC框架
自己手撸了一个nettyRPC框架,希望在这里给有兴趣的同学们做个参考. 要想实现nettyrpc需要了解的技术要点如下: spring的自定义注解.spring的bean的有关初始化. 反射和动态代 ...
- 设计模式:代理模式是什么,Spring AOP还和它有关系?
接着学习设计模式系列,今天讲解的是代理模式. 定义 什么是代理模式? 代理模式,也叫委托模式,其定义是给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用.它包含了三个角色: Subject: ...
- mimalloc剖析
mimalloc是微软最近开源的一个malloc实现,其实验数据表明相比于jemalloc.tcmalloc等实现大约快了10%.其通过将空闲块列表(Free List)进行分片(Sharding)来 ...
- 个人永久性免费-Excel催化剂功能第62波-单元格区域内数据加解密处理,最有效地保护数据方式
Excel的数据保护能力有限,诸如之前提及过的工作表保护.工作薄保护等,都是十分微弱的保护措施,而对于强保护的工作薄打开密码来说,它像是个总开关一样,要么全不能看,要么就全看到.有这样的场景需求,一份 ...
- Spring 自动生成getter和setter方法 tostring方法
添加maven依赖 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency& ...
- C语言入门4-运算符和表达式
一. 分类 C语言一共有34种运算符,10种运算类型,本节我们要掌握的有( 7 种) 算术运算符(+.-.*./.%). 关系运算符(>.>=.==.!=.<.<=). ...
- C#7.3 新增功能
连载目录 [已更新最新开发文章,点击查看详细] C# 7.3 版本有两个主要主题. 第一个主题提供使安全代码的性能与不安全代码的性能一样好的功能. 第二个主题提供对现有功能的增量改进. 此外,在 ...
- leetcode 48 矩阵旋转可以这么简单
一行代码解决矩阵旋转(方法三). 方法1: 坐标法 def rotate(self, matrix): n = len(matrix) # 求出矩阵长度 m = (n + 1) // 2 # 求出层数 ...
- 转 - RPC调用和HTTP调用的区别
很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单 ...