【题解】NOIP2017逛公园(DP)
【题解】NOIP2017逛公园(DP)
第一次交挂了27分...我是不是必将惨败了...
考虑这样一种做法,设\(d_i\)表示从该节点到n节点的最短路径,\(dp(i,k)\)表示从\(i\)节点到\(n\)多走至多\(k\)距离的方案数。转移相当于枚举走哪条边,状态的变化是如果走这条边会比最短路多多少。
转移方程
\]
直接用dfs实现转移(记得判环)即可。
...
...
...
但是我们不能这么敷衍,转移顺序究竟是什么?
可以这样理解:反向跑最短路后,可以建成一个新图\(G'=(V,E)\)其中,\(E\)的原图边的子集,且对于边\((u,v)\)当且仅当\(d_u \ge d_v\)时存在(d是反向最短路数组)。这个新图若非DAG则无解/无限解。所以现在保证是个DAG了,所以拓扑排序之后可以转移了。(存在一个)拓扑排序就是DFS回溯顺序。
时间复杂度\(O(T(mk+nk+n\log m))\)。合法\(0\)边越多越能顶到这个复杂度。
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e5+5;
template<class M>
struct HEAP{
M data[maxn*2];
int cnt;
inline void down(const int&pos){
for(int t=pos,k;(t<<1)<=cnt;t=k){
k=t<<1;
if(k<cnt&&data[k|1]<data[k]) k|=1;
if(data[t]>data[k]) swap(data[t],data[k]);
else return;
}
}
inline void up(const int&pos){
for(int t=pos;t>>1;t>>=1)
if(data[t]<data[t>>1]) swap(data[t],data[t>>1]);
else return;
}
inline void push(const M&x){data[++cnt]=x,up(cnt);}
inline void pop(){swap(data[1],data[cnt--]);down(1);}
inline M top(){return data[1];}
inline int size(){return cnt;}
};
HEAP< pair<int,int> > q;
struct E{
int to,nx,w;
E(){to=nx=w=0;}
E(const int&x,const int&y,const int&z){to=x; nx=y; w=z;}
}e[maxn<<2];
int head[maxn],cnt,head0[maxn];
inline void add(const int&fr,const int&to,const int&w,int*h=head){e[++cnt]=E(to,h[fr],w),h[fr]=cnt;}
int d[maxn],n,m,k,mod;
typedef pair<int,int> P;
const int inf=1e9;
inline void dij(){
for(int t=1;t<=n;++t) d[t]=inf;
q.push((P){d[n]=0,n});
while(q.size()){
P now=q.top(); q.pop();
if(now.first>d[now.second]) continue;
for(int t=head[now.second];t;t=e[t].nx)
if(d[e[t].to]>d[now.second]+e[t].w)
q.push((P){d[e[t].to]=d[now.second]+e[t].w,e[t].to});
}
}
int dp[55][maxn];
bool usd[55][maxn];
bool in[55][maxn];
int dfs(const int&now,const int&k){
if(in[k][now])return -1;
if(usd[k][now]) return dp[k][now];
dp[k][now]=now==n;
in[k][now]=usd[k][now]=1;
for(int t=head0[now];t;t=e[t].nx){
int g=e[t].w-(d[now]-d[e[t].to]),ret;
if(g>k)continue;
if(ret=dfs(e[t].to,k-g),-1==ret) return dp[k][now]=-1;
dp[k][now]=(dp[k][now]+ret)%mod;
}
in[k][now]=0;
return dp[k][now];
}
int main(){
int T=qr();
while(T--){
cnt=0;
n=qr(); m=qr(); k=qr(); mod=qr();
for(register int t=0;t<=n;++t) head[t]=head0[t]=0;
for(int i=0;i<=k;++i)
for(register int t=0;t<=n;++t)
dp[i][t]=usd[i][t]=in[i][t]=0;
for(int t=1,t1,t2,t3;t<=m;++t)
t1=qr(),t2=qr(),t3=qr(),add(t2,t1,t3),add(t1,t2,t3,head0);
dij();
//for(int t=1;t<=n;++t) printf("%d\n",d[t]);
printf("%d\n",dfs(1,k));
}
return 0;
}
【题解】NOIP2017逛公园(DP)的更多相关文章
- $[NOIp2017]$ 逛公园 $dp$/记搜
\(Des\) 给定一个有向图,起点为\(1\),终点为\(n\),求和最短路相差不超过\(k\)的路径数量.有\(0\)边.如果有无数条,则输出\(-1\). \(n\leq 10^5,k\leq ...
- [NOIP2017] 逛公园
[NOIP2017] 逛公园 题目大意: 给定一张图,询问长度 不超过1到n的最短路长度加k 的1到n的路径 有多少条. 数据范围: 点数\(n \le 10^5\) ,边数\(m \le 2*10^ ...
- 【比赛】NOIP2017 逛公园
考试的时候灵光一闪,瞬间推出DP方程,但是不知道怎么判-1,然后?然后就炸了. 后来发现,我只要把拓扑和DP分开,中间加一个判断,就AC了,可惜. 看这道题,我们首先来想有哪些情况是-1:只要有零环在 ...
- NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】
题目描述 策策同学特别喜欢逛公园.公园可以看成一张NNN个点MMM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NNN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花 ...
- NOIP2017逛公园(dp+最短路)
策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策策每天都会 ...
- [NOIP2017]逛公园 题解
我连D1T3都不会我联赛完蛋了 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 N 个点 M 条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口, N 号点是公园的出口,每条边有一个非负 ...
- P3953 逛公园(dp,最短路)
P3953 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经 ...
- [NOIP2017] 逛公园 解题报告(DP)
我很不想说 在我的AC代码上我打了表,但实在没有办法了.莫名的8,9个点RE.然而即便是打表...也花了我很久. 这大概是NOIP2017最难的题了,为了让不懂的人更容易理解,这篇题解会比较详细 我的 ...
- [NOIP2017]逛公园 最短路+拓扑排序+dp
题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...
随机推荐
- @loj - 2496@ 「AHOI / HNOI2018」毒瘤
目录 @description@ @solution@ @accepted code@ @details@ @description@ 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的 ...
- oracle函数 power(x,y)
[功能]返回x的y次幂 [参数]x,y 数字型表达式 [返回]数字 [示例] select power(2.5,2),power(1.5,0),power(20,-1) from dual; 返回:6 ...
- 洛谷P3957 跳房子 题解 二分答案/DP/RMQ
题目链接:https://www.luogu.org/problem/P3957 这道题目我用到了如下算法: 线段树求区间最大值: 二分答案: DP求每一次枚举答案g时是否能够找到 \(\ge k\) ...
- Python--day62--使用Bootstrap样式的出版社
没有使用之前: 使用Bootstrap样式之后:
- webpack学习(一)项目中安装webpack
如何在项目中安装webpack,webpack-cli? 前提:电脑安装了 node和npm包管理工具 1 创建项目文件夹或者在已有的项目中打开终端 输入相关命令: npm init 因为已经安装好 ...
- 阿里巴巴Java编程规范考试
阿里巴巴Java编程规范考试 今天在阿里云官网把阿里巴巴Java编程规范认证考试考过了, 写下这篇文章总结一下考试中需要注意的知识点, 主体内容还是要直接看规范: 编程规约 异常日志 单元测试 安全规 ...
- cfp大纲
AFP基础知识 本章共14个考点,考试考15分左右. 本章重点: .职业道德准则 .家庭财务分析:净值的计算.储蓄的计算 .简单的财务比率分析 .金融理财和法律:企业组织形式.夫妻公共财产制度.财产分 ...
- 【git】Git回退代码到指定版本
1. 查看所有的历史版本,获取你git的某个历史版本的id, git log2. 回退本地代码库:git reset --hard ID3. 推送到远程服务器:git push -f -u origi ...
- 「THUPC 2019」不等式 / inequality
https://loj.ac/problem/6620 高中数学好题.. |kx+b|的函数图像很直观,直接考虑函数图像: 一定只有一段极小值点! 这个点就是最小值了 特点:斜率为0! 而且发现,如果 ...
- P1033 沙茶会传染
题目描述 已知沙茶会传染,而且每一轮每一个沙茶都会传染给另外x个不是沙茶的人,让他们变成沙茶. 已知一开始人群中只有一只沙茶,请问n轮之后人群中会有多少沙茶? 输入格式 两个数 \(x(1 \le x ...