NOIP 2017 逛公园 - 动态规划 - 最短路
跑一遍最短路。
一个点拆$K + 1$个点,变成一个DAG上路径计数问题。直接拓扑排序加动态规划,如果有一个$n$号点的剩余度数非0,就一个合法的路径上存在零环(这样可以无线走了)。
于是成功T掉了。
把拓扑排序变成不建图,从$n$开始记忆化搜索,然后就过了。
我居然把模数P打错成M调了一个上午,果然我菜啊。。。
下面这份代码获得了 97 分的好成绩,我也不知道发生了什么。
Code
/**
* Uoj
* Problem#331
* Accepted
* Time: 2392ms
* Memory: 28196k
*/
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef bool boolean; typedef pair<int, int> pii; const int N = 1e5 + , M = 2e5 + , Kmx = ; const signed int inf = (signed) (~0u >> ); template <typename T>
void pfill(T* pst, const T* ped, T val) {
for ( ; pst != ped; *(pst++) = val);
} typedef class Edge {
public:
int ed, nx, w; Edge(int ed = , int nx = , int w = ):ed(ed), nx(nx), w(w) { }
}Edge; typedef class MapManager {
public:
int *h;
vector<Edge> es; MapManager(int n) {
h = new int[(n + )];
} void init(int n) {
pfill(h + , h + n + , -);
es.clear();
} void addEdge(int u, int v, int w) {
es.push_back(Edge(v, h[u], w));
h[u] = (signed) es.size() - ;
} Edge& operator [] (int p) {
return es[p];
}
}MapManager; typedef class Node {
public:
int p, dis; Node(int p = , int dis = ):p(p), dis(dis) { } boolean operator < (Node b) const {
return dis > b.dis;
}
}Node; int n, m, K, P;
MapManager g(N), _g(N); int add(int a, int b) {
return ((a += b) >= P) ? (a - P) : (a);
} inline void init() {
scanf("%d%d%d%d", &n, &m, &K, &P);
g.init(n + ), _g.init(n + );
for (int i = , u, v, w; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
g.addEdge(u, v, w);
_g.addEdge(v, u, w);
}
} int f[N];
priority_queue<Node> que; int& operator * (Node p) {
return f[p.p];
} void dijstra() {
pfill(f + , f + n + , inf);
que.push(Node(, f[] = ));
while (!que.empty()) {
Node e = que.top();
que.pop();
if (*e != e.dis)
continue;
for (int i = g.h[e.p]; ~i; i = g[i].nx)
if (*e + g[i].w < f[g[i].ed])
que.push(Node(g[i].ed, f[g[i].ed] = *e + g[i].w));
}
} int h[N][Kmx];
unsigned char vis[N][Kmx];
boolean cir = false;
int dp(int p, int dif) {
if (dif > K)
return ;
if (dif < )
return ;
assert(dif >= );
if (vis[p][dif] & )
return cir = true;
if (vis[p][dif] & )
return h[p][dif];
vis[p][dif] |= , h[p][dif] = (p == && dif == );
for (int i = _g.h[p], e, nd; ~i; i = _g[i].nx) {
e = _g[i].ed;
if (f[e] == inf)
continue;
nd = f[p] + dif - _g[i].w - f[e];
h[p][dif] = add(h[p][dif], dp(e, nd));
if (cir)
return ;
}
vis[p][dif] ^= ;
return h[p][dif];
} inline void solve() {
dijstra();
if (f[n] == inf) {
puts("");
return;
}
cir = false;
pfill(vis[], vis[n + ], (unsigned char));
int rt = dp(n, );
for (int i = ; i <= K && !cir; i++)
rt = add(rt, dp(n, i));
printf("%d\n", (cir) ? (-) : (rt));
} int T;
int main() {
scanf("%d", &T);
while (T--) {
init();
solve();
}
return ;
}
NOIP 2017 逛公园 - 动态规划 - 最短路的更多相关文章
- NOIP 2017 逛公园 记忆化搜索 最短路 好题
题目描述: 策策同学特别喜欢逛公园.公园可以看成一张N个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. ...
- [NOIp 2017]逛公园
Description 策策同学特别喜欢逛公园.公园可以看成一张$N$个点$M$条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,$N$号点是公园的出口,每条边有一个非负权值, 代表策策经 ...
- 洛谷 P3953 [ NOIP 2017 ] 逛公园 —— 最短路DP
题目:https://www.luogu.org/problemnew/show/P3953 主要是看题解...还是觉得好难想啊... dfs DP,剩余容量的损耗是边权减去两点最短路差值...表示对 ...
- NOIP 2017 逛公园 题解
题面 这道题是一道不错的计数类DP: 首先我们一定要跑一遍dijkstra来求得每个点到1号点的最短路: 注意题干,题中并没有说所有点都可以到达n好点,只说了存在一条1号点到n号点的路径:所以我们在反 ...
- 【NOIP2017】逛公园(最短路图,拓扑排序,计数DP)
题意: 策策同学特别喜欢逛公园. 公园可以看成一张 N 个点 M 条边构成的有向图,且没有自环和重边.其中 1 号点是公园的入口, N 号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花 ...
- P3953 逛公园(dp,最短路)
P3953 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经 ...
- Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)
跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可.wa了三发感觉非常凉. #include<iostream> #include<cstdio> #include&l ...
- 2018.11.01 洛谷P3953 逛公园(最短路+dp)
传送门 设f[i][j]f[i][j]f[i][j]表示跟最短路差值为iii当前在点jjj的方案数. in[i][j]in[i][j]in[i][j]表示在被选择的集合当中. 大力记忆化搜索就行了. ...
- NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)
神tm比赛时多清个零就有60了T T 首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP.设f[i][j]表示比最短路多走i的长度,到j的方案数. 我们发现如果在最短路上的和零边会有后向性, ...
随机推荐
- Confluo: Distributed Monitoring and Diagnosis Stack for High-speed Networks
https://rise.cs.berkeley.edu/blog/confluo-millisecond-level-queries-on-large-scale-streaming-data/ht ...
- ip通信第七周
局域网的优点:1.具有较高的数据传输率 2.具有较低的误码率 3.具有较低的时延 4.能进行广播 网桥的基本特征:1.网桥在数据链录层上实现局域网互连 2.网桥能够互连两个采用不同数据链路层协议,不同 ...
- WinAPI 字符及字符串函数(15): CharNext、CharPrev
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...
- 多线程之Lock的基本介绍
基本介绍 java.util.concurrent.locks是java1.5之后出现的一种锁实现方式,是一个接口.但是在这之前已经有一个同步机制的实现就是synchronized关键字,那为什么还要 ...
- python 包下载地址
https://www.lfd.uci.edu/~gohlke/pythonlibs/
- linux获取网络信息函数
获取IP地址 int sys_getIP(char *ip_addr) { ] = {"ifconfig eth0 | grep inet | cut -d: -f2 | cut -d' ' ...
- JS生成当前月份包括最近12个月内的月份
var last_year_month = function() { var result = []; for(var i = 0; i < 12; i++) { var d = new Dat ...
- 20175211 2018-2019-2 《Java程序设计》第五周学习总结
目录 教材学习内容总结 第六章 接口与实现 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 学习进度条 参考资料 教材学习内容总结 第六章 接口与实现 6.1 接口 ...
- Kali Hydra SSL issue, xHydra (GUI version of Hydra) works just fine
First find the source code. (https://is.gd/LlS5Sy) - Example search Once located you must download i ...
- vue中上传文件之multipart/form-data
首先在项目里用了拦截器的,由于拦截器会将传递的参数转成对象,所以你i提交的时候会发现multipart/form-data或转变成application/json 其次关于input的文件上传是需要一 ...