NOIP2017逛公园(dp+最短路)
策策同学特别喜欢逛公园。公园可以看成一张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+最短路)的更多相关文章
- 【题解】NOIP2017逛公园(DP)
[题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...
- P3953 逛公园(dp,最短路)
P3953 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经 ...
- Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)
跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可.wa了三发感觉非常凉. #include<iostream> #include<cstdio> #include&l ...
- $[NOIp2017]$ 逛公园 $dp$/记搜
\(Des\) 给定一个有向图,起点为\(1\),终点为\(n\),求和最短路相差不超过\(k\)的路径数量.有\(0\)边.如果有无数条,则输出\(-1\). \(n\leq 10^5,k\leq ...
- [NOIP2017] 逛公园 【最短路】【强连通分量】
题目分析: 首先考虑无数条的情况.出现这种情况一定是一条合法路径经过了$ 0 $环中的点.那么预先判出$ 0 $环中的点和其与$ 1 $和$ n $的距离.加起来若离最短路径不超过$ k $则输出$ ...
- [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 号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花 ...
随机推荐
- Visual Studio 2010 Shortcuts
Uploaded by ProNotion, updated on 11/28/2013 by jmb Platform: Windows/ English PDF Print Hide ...
- ubuntu使用squid搭建代理
安装squid //检查是否安装squid which squid // apt update sudo apt install squid 配置squid的配置文件squid.conf //备份sq ...
- Yii的操作提示框
效果如图 HTML + CSS<style> div.error{ background: #FFE0E0; border: 2px solid #FFA0A0; padding: 10p ...
- vue二次实战
vue爬坑之路 npm uninstall 模块名(删除指定模块) https://www.cnblogs.com/wisewrong/p/6255817.html vue快速入门 https://s ...
- ES6/ES2015的一些特性的简单使
1.一些常用的ES6的特性: let, const, class, extends, super, arrow functions, template string, destructuring, d ...
- flutter图片铺满父框
正常我们需要显示一张图片,会用到Image这个控件. 打个比方,我们加载一张本地的图片, 先看一下这个Image.asset的源码: Image.asset(String name, { Key ke ...
- python学习笔记(6)--条件分支语句
if xxxx: coding if xxxx: coding else: coding if xxxx: coding elif xxx: coding …… else: coding 或者一种简洁 ...
- python数学第八天【协方差】
- wget 下载网页
如有转载,不胜荣幸.http://www.cnblogs.com/aaron-agu/ wget --http-user=username --http-passwd=password http:/w ...
- LDOOP设置关联后超出新起一页LinkNewPage
关联打印的时候,top,left关联位置是相对于被关联打印项的偏移值,具体可查看本博客相关介绍博文:LODOP打印控件关联输出各内容 正常情况下,超文本超过打印项高度,或纸张高度会自动分页,如果超文本 ...