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

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

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

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

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

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

Solution

看这像个分层图(其实也是分层图2333),首先一眼看到最短路计数,30pts到手。。

我们先把最短路DAG搞出来,拓扑一遍。

什么情况有无穷多解,有0环,我们拓扑完之后,如果还有点有入度,就是无解。

考虑到转移是和k相关的,而且是从小往大转移的,所以我们在枚举k之后,对于i->i转移的转移,我们按照拓扑序进行dp,对于i->i+k的转移,按照分层图的顺序转移就可以了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 100002
#define M 200002
#define mm make_pair
using namespace std;
queue<int>q1;
priority_queue<pair<int,int> >q;
int dis[N],du[N],head[N],tot,n,t[N],tt,T,m,k,p,dp[N][],ans,tttt;
bool vis[N];
struct fdd{
int n,to,l;
}e[M];
inline void unit(){
tot=;
memset(head,,sizeof(head));
memset(dp,,sizeof(dp));tt=;tttt=;
memset(du,,sizeof(du));
}
inline void add(int u,int v,int l){
e[++tot].n=head[u];
e[tot].to=v;e[tot].l=l;
head[u]=tot;
}
inline void dij(int s){
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
dis[s]=;q.push(mm(,s));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=;
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].l){
dis[v]=dis[u]+e[i].l;
q.push(mm(-dis[v],v));
}
}
}
}
inline void topo(){
for(int i=;i<=n;++i)if(!du[i])q1.push(i);
while(!q1.empty()){
int u=q1.front();q1.pop();t[++tt]=u;
for(int i=head[u];i;i=e[i].n)if(dis[e[i].to]==dis[u]+e[i].l){
int v=e[i].to;
if(!--du[v])q1.push(v);
}
}
for(int i=;i<=n;++i)if(du[i])tttt=;
}
inline int rd(){
int x=;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c)){
x=(x<<)+(x<<)+(c^);
c=getchar();
}
return x;
}
int main(){
T=rd();
while(T--){
unit();
int u,v,w;
n=rd();m=rd();k=rd();p=rd();
for(int i=;i<=m;++i){
u=rd();v=rd();w=rd();add(u,v,w);
}
dij();
memset(vis,,sizeof(vis));
for(int u=;u<=n;++u){
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(dis[u]+e[i].l==dis[v])du[v]++;
}
}
topo();
if(tttt){
printf("-1\n");
continue;
}
dp[][]=;
for(int i=;i<=k;++i){
for(u=;u<=tt;++u)
for(int j=head[t[u]];j;j=e[j].n)if(dis[t[u]]+e[j].l==dis[e[j].to]){
int v=e[j].to;
(dp[v][i]+=dp[t[u]][i])%=p;
}
for(int u=;u<=n;++u)
for(int j=head[u];j;j=e[j].n)if(dis[u]+e[j].l!=dis[e[j].to]){
int v=e[j].to;
int kk=dis[u]-dis[v]+e[j].l+i;
if(kk<=k)(dp[v][kk]+=dp[u][i])%=p;
}
}
ans=;
for(int i=;i<=k;++i)(ans+=dp[n][i])%=p;
printf("%d\n",ans);
}
return ;
}

NOIP2017逛公园(dp+最短路)的更多相关文章

  1. 【题解】NOIP2017逛公园(DP)

    [题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n​节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...

  2. P3953 逛公园(dp,最短路)

    P3953 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经 ...

  3. Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)

    跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可.wa了三发感觉非常凉. #include<iostream> #include<cstdio> #include&l ...

  4. $[NOIp2017]$ 逛公园 $dp$/记搜

    \(Des\) 给定一个有向图,起点为\(1\),终点为\(n\),求和最短路相差不超过\(k\)的路径数量.有\(0\)边.如果有无数条,则输出\(-1\). \(n\leq 10^5,k\leq ...

  5. [NOIP2017] 逛公园 【最短路】【强连通分量】

    题目分析: 首先考虑无数条的情况.出现这种情况一定是一条合法路径经过了$ 0 $环中的点.那么预先判出$ 0 $环中的点和其与$ 1 $和$ n $的距离.加起来若离最短路径不超过$ k $则输出$ ...

  6. [NOIP2017] 逛公园

    [NOIP2017] 逛公园 题目大意: 给定一张图,询问长度 不超过1到n的最短路长度加k 的1到n的路径 有多少条. 数据范围: 点数\(n \le 10^5\) ,边数\(m \le 2*10^ ...

  7. 【比赛】NOIP2017 逛公园

    考试的时候灵光一闪,瞬间推出DP方程,但是不知道怎么判-1,然后?然后就炸了. 后来发现,我只要把拓扑和DP分开,中间加一个判断,就AC了,可惜. 看这道题,我们首先来想有哪些情况是-1:只要有零环在 ...

  8. NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】

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

  9. 【NOIP2017】逛公园(最短路图,拓扑排序,计数DP)

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

随机推荐

  1. 关于spring的源码的理解

    从最基础的Hello World开始. spring的Hello World就三行代码: public void test() { ApplicationContext context = new C ...

  2. tomcat8.0部署启动

    http://tomcat.apache.org/download-80.cgi 打开命令行提示符窗口, 进入Tomcat安装目录, 进入bin目录下, 输入:service.bat install  ...

  3. [转帖]web安全:QQ号快速登录漏洞及被盗原理

    web安全:QQ号快速登录漏洞及被盗原理 https://www.cnblogs.com/1996V/p/7481823.html 看了下 QQ的确监听 端口 大神牛B 自己这一块一直没深入学习过.. ...

  4. 解决 linux 下面解压缩 中文文件名乱码问题的方法 unzip -O CP936

    Linux 解压缩 zip包中文目录出现乱码的问题. 出现问题如图示: unzip -O CP936 xxx.zip 用这种方式处理一下就好了.

  5. python之路--动态传参,作用域,函数嵌套

    一 . 动态传参(重点)  * ,  ** * 与 ** * 在形参位置. * 表示不定参数, 接收的是位置参数 接收到的位置参数的动态传参: 都是元组 def eat(*food): # 在形参这里 ...

  6. Navicat Preminum

    此软件在连接的时候,需要这样: 新建链接==>连接属性==>编码选择自动==>如果此时点击确定的话,会把整个服务器的所有数据库都打开, 我们也可以只打开指定的数据库, 点击高级==& ...

  7. mysql第一天【mysqldump导出数据和mysql导入数据】

    1.使用mysqldump导出数据到本地sql文件 在mysql>bin下执行: 例如: mysqldump -hrm-2ze8mpi5i65429l1qvo.mysql.rds.aliyunc ...

  8. 三、zookeeper安装

    一.简介 二.下载解压: #wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.12/zookeeper-3.4.12.tar ...

  9. How to mount EFI on macOS

    mount -t msdos /dev/disk0s1 /volumes/efi

  10. bmi

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...