跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可。wa了三发感觉非常凉。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define N 100010
#define M 200010
#define K 51
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,m,k,P,p[N],d[N],from[M],f[N][K],Q[N],degree[N],t;
bool flag[N];
struct data{int to,nxt,len;
}edge[M];
struct data2
{
int x,d;
bool operator <(const data2&a) const
{
return d>a.d;
}
};
priority_queue<data2> q;
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z;p[x]=t;}
void dijkstra()
{
memset(d,,sizeof(d));d[]=;
memset(flag,,sizeof(flag));
q.push((data2){,});
for (;;)
{
while (!q.empty()&&flag[q.top().x]) q.pop();
if (q.empty()) break;
data2 x=q.top();q.pop();flag[x.x]=;
for (int i=p[x.x];i;i=edge[i].nxt)
if (x.d+edge[i].len<d[edge[i].to])
{
d[edge[i].to]=x.d+edge[i].len;
q.push((data2){edge[i].to,d[edge[i].to]});
}
}
}
bool topsort()
{
memset(degree,,sizeof(degree));
for (int i=;i<=m;i++)
if (d[from[i]]+edge[i].len==d[edge[i].to]) degree[edge[i].to]++;
int head=,tail=;for (int i=;i<=n;i++) if (!degree[i]) Q[++tail]=i;
while (head<tail&&tail<n)
{
int x=Q[++head];
for (int i=p[x];i;i=edge[i].nxt)
if (d[x]+edge[i].len==d[edge[i].to])
{
degree[edge[i].to]--;
if (!degree[edge[i].to]) Q[++tail]=edge[i].to;
}
}
return tail<n;
}
int main()
{
T=read();
while (T--)
{
n=read(),m=read(),k=read(),P=read();
t=;memset(p,,sizeof(p));
for (int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
from[i]=x;addedge(x,y,z);
}
dijkstra();
if (topsort()) cout<<-<<endl;
else
{
memset(f,,sizeof(f));f[][]=;
for (int i=;i<=k;i++)
for (int j=;j<=n;j++)
{
int x=Q[j];
for (int y=p[x];y;y=edge[y].nxt)
{
int u=d[x]+edge[y].len-d[edge[y].to]+i;
if (u<=k) inc(f[edge[y].to][u],f[x][i]);
}
}
int ans=;
for (int i=;i<=k;i++) inc(ans,f[n][i]);
cout<<ans<<endl;
}
}
return ;
}

Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)的更多相关文章

  1. [NOIP2017]逛公园 最短路+拓扑排序+dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...

  2. [Luogu P3953] 逛公园 (最短路+拓扑排序+DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易 ...

  3. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

  4. [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)

    题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...

  5. luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)

    先跑一边dijkstra算出从1到i的最短距离dis[i] 然后建反向边 从n开始记忆化搜索,(p,k)表示1到p的距离=dis[p]+k的方案数 答案就是$\sum\limits_{i=0}^{k} ...

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

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

  7. 【比赛】NOIP2017 逛公园

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

  8. [NOIP2017] 逛公园

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

  9. NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)

    神tm比赛时多清个零就有60了T T 首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP.设f[i][j]表示比最短路多走i的长度,到j的方案数. 我们发现如果在最短路上的和零边会有后向性, ...

随机推荐

  1. C# register global hotkey ,onekey 注册多个全局热键以及单个全局热键

    我们需要用非Hook的方法,来给我们的app 或者winform注册热键. 就像下面的 , 欧陆词典注册的一个热键F6一样, 在winform最小化的情况下,也能够全局响应热键. 这里使用系统API来 ...

  2. QQ群排名优化到霸屏的策略怎么做?

    谈起QQ群排名霸屏,首先要弄清楚概念,有些刚接触QQ群的朋友可能不太了解,所谓的QQ群排名霸屏,就是指当你的客户群体搜索QQ群某个关键词时,出现在QQ群搜索结果前面的群,全部或者大部分都是我们自己的群 ...

  3. scala成长之路(7)函数进阶——可能是史上最浅显易懂的闭包教程

    由于scala中函数内部能定义函数,且函数能作为函数的返回值,那么问题来了,当返回的函数使用了外层函数的局部变量时,会发生什么呢?没错,就产生是闭包. 关于闭包的解释网上一大堆,但基本上都是照葫芦画瓢 ...

  4. go学习笔记-流程控制(if/else,for/range)

    流程控制(if/else,for/range) if if条件判断语句的语法概括起来就是:如果满足条件就做某事,否则做另一件事. func testIf() { num := 10 if num &l ...

  5. codeblocks编译出错问题的解答!(编译c++ 或者c程序)

    典型错误:https://blog.csdn.net/jingmiaa/article/details/52054204 MinGW下载并配置gcc/g++编译环境:https://blog.csdn ...

  6. [【转】ubuntu 16.10 Server 安装及基本部署

    一.Ubuntu Server 16.10 LTS 系统安装 Ubuntu 16.10 分为 桌面版 (desktop)和服务器版(Server).两者对于用户而言,最大的区别在于桌面版有图形操作界面 ...

  7. 13 IO多路复用 (未完成)

    IO多路复用 6.select版-TCP服务器:最多1024 import select import socket import sys server = socket.socket(socket. ...

  8. LeetCode:7. Reverse Integer(Easy)

    题目要求:将给出的整数进行逆序输出 注意:整数的最大范围-2147483648-2147483647,当翻转后的数超出范围后返回0 思路:对给出的整数除以10,取余和取整:然后对取整部分继续取余和取整 ...

  9. vs13发布web程序 iis上

    一.配置iis 1,找到控制面板--程序--启用或关闭Windows功能 2,从列表中选择Internet Infomation Services,并且把相应的功能条目勾选上,如果不清楚,可以全部选中 ...

  10. CC3100BoosterPack和CC31XXEMUBOOST板子的测试

    1. 先测试右边的CC3100BoosterPack,测试发现LDO坏了,无法输出3.3V,所以只能用左边的板子供电. 2. 插上CC31XXEMUBOOST板子的J1,两个板子插在一起,等待驱动安装 ...