题目
首先我们跑出从\(1\)出发的最短路\(d1\)和反图上从\(n\)出发的最短路\(dn\)。
然后我们处理出长度不超过\(d1_n+k\)的最短路边集,给它拓扑排序。
如果存在环,那么这个环一定是一个\(0\)环,此时是无解的。
否则我们把它的拓扑序跑出来。
对于一条边\((u,v,w)\),如果我们走这条边,会让路径长度比最短路大\(d1_u+w-d1_v\)。
那么我们设\(f_{i,j}\)表示走到第\(i\)个点,走过的路径长度是\(d1_i+j\)。
从小到大枚举\(j\),按拓扑序转移一遍,再把\(d1_u+w-d1_v\neq0\)的所有边转移一遍即可。

#include<bits/stdc++.h>
#define pi pair<int,int>
#define pb push_back
using namespace std;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
const int N=100007;
vector<pi>E[N];priority_queue<pi>q;stack<int>Q;
struct edge{int u,v,w;}e[N<<1];
int n,m,k,P,cnt,Tvis,dis[2][N],vis[N],deg[N],pos[N],f[N][51];
void inc(int &a,int b){a+=b,a=a>=P? a-P:a;}
void clearedge(){for(int i=1;i<=n;++i)E[i].clear();}
void cleardeg(){memset(deg,0,n+1<<2);}
void add(int u,int v,int w){E[u].pb(pi(v,w));}
void dij(int S,int id)
{
    memset(dis[id],0x3f,n+1<<2),++Tvis,q.push(pi(dis[id][S]=0,S));int u;
    while(!q.empty())
    {
    u=q.top().second,q.pop();if(vis[u]==Tvis)continue;vis[u]=Tvis;
    for(auto [v,w]:E[u])if(dis[id][u]+w<dis[id][v])dis[id][v]=dis[id][u]+w,q.push(pi(-dis[id][v],v));
    }
}
void toposort()
{
    cnt=0;int u;Q.push(1);
    while(!Q.empty())
    {
    u=Q.top(),Q.pop(),pos[++cnt]=u;
    for(auto [v,w]:E[u])if(!(--deg[v]))Q.push(v);
    }
}
int main()
{
    int i,j,flg;
    for(int T=read();T;--T)
    {
    n=read(),m=read(),k=read(),P=read();
    for(i=1;i<=m;++i)e[i]=(edge){read(),read(),read()};
    clearedge();
    for(i=1;i<=m;++i)add(e[i].u,e[i].v,e[i].w);
    dij(1,0);
    clearedge();
    for(i=1;i<=m;++i)add(e[i].v,e[i].u,e[i].w);
    dij(n,1);
    clearedge(),cleardeg();
    for(i=1;i<=m;++i)if(dis[0][e[i].u]+dis[1][e[i].v]+e[i].w<=dis[0][n]+k&&dis[0][e[i].u]+e[i].w==dis[0][e[i].v])add(e[i].u,e[i].v,0),++deg[e[i].v];
    for(i=1;i<=m;++i)e[i].w=dis[0][e[i].u]+e[i].w-dis[0][e[i].v];
    toposort();
    flg=0;
    for(i=1;i<=n;++i)if(deg[i]){flg=1;break;}
    if(flg){puts("-1");continue;}
    memset(f,0,sizeof f),f[1][0]=1;
    for(i=0;i<=k;++i)
    {
        for(j=1;j<=cnt;++j)for(auto [v,w]:E[pos[j]])inc(f[v][i],f[pos[j]][i]);
        for(j=1;j<=m;++j)if(e[j].w&&i+e[j].w<=k)inc(f[e[j].v][i+e[j].w],f[e[j].u][i]);
    }
    for(i=flg=0;i<=k;++i)inc(flg,f[n][i]);
    printf("%d\n",flg);
    }
}

```

Luogu P3953 [NOIP2017]逛公园的更多相关文章

  1. Luogu 3953[NOIP2017] 逛公园 堆优化dijkstra + 记忆化搜索

    题解 首先肯定是要求出单源最短路的,我用了堆优化dijikstra ,复杂度 mlogm,值得拥有!(只不过我在定义优先队列时把greater 打成了 less调了好久 然后我们就求出了$i$到源点的 ...

  2. 洛谷P3953 [NOIP2017]逛公园

    K<=50,感觉可以DP 先建反图求出从n到各个点的最短路,然后在正图上DP 设f[当前点][比最短路多走的距离]=方案数 转移显然是 $f[v][res]=\sum f[u][res+tmp] ...

  3. [luogu P3953] [noip2017 d1t3] 逛公园

    [luogu P3953] [noip2017 d1t3] 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张$N$个点$M$条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,$N ...

  4. [NOIP2017] 逛公园

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

  5. 【比赛】NOIP2017 逛公园

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

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

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

  7. NOIP2017逛公园(dp+最短路)

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

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

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

  9. [NOIP2017]逛公园 题解

    我连D1T3都不会我联赛完蛋了 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 N 个点 M 条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口, N 号点是公园的出口,每条边有一个非负 ...

随机推荐

  1. Java多线程和并发(四),线程返回值获取方式和Callable接口

    目录 1.主线程等待法 2.使用Thread类的join()阻塞当前线程,等待子线程执行完毕 3.通过Callable接口实现:通过FutureTask Or线程池获取 四.线程返回值获取方式和Cal ...

  2. 51 Nod 1161 Partial sums

    1161 Partial Sums  题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  取消关注 给出一个数组A,经过一次 ...

  3. HNOI2010 平面图判定(planar)

    题目链接:戳我 我怎么知道平面图有这个性质?? 对于一个平面图,它的边数不超过点数的\(3n-6\) 所以可以直接把边数多的特判掉,剩下的图中边数和点数就是一个数量级的了. 因为这个图存在欧拉回路,所 ...

  4. 1502: [NOI2005]月下柠檬树

    一堆圆台平行光的投影 在草稿纸上画一下,发现对于一个圆,它投影完还是一个半径不变的圆. 定义树的轴在投影平面上经过的点为原点,定一个正方向,建立平面直角坐标系, 能发现,对于一个半径为\(r\),高度 ...

  5. [笔记]makefile编写

    makefile的隐含规则默认处理第一个目标 函数:wildcard可以进行文本匹配 patsubst内容替换 变量: $@代表目标 $^  代表全部依赖 $<  第一个依赖 $?   第一个变 ...

  6. Java实现QQ微信轰炸机1.2(斗图乞丐版)

    之前有小可爱评论可以实现斗图的功能,原理上是行的通的,所以我就稍微改了一下,能够实现单个图片循环轰炸,如果大家感兴趣也可以自己探究实现多张图片循环轰炸,不废话了,直接上源码package QQWcha ...

  7. 出现org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER, 且出现无法找到Maven的依赖的问题

    解决方案:Build Path -> Java Build Path ->Libraries ->Add Library ->Maven Managed Dependences ...

  8. 20175215 2018-2019-2 第七周java课程学习总结

    第八章 常用实用类 8.1 String类 Java专门提供了用来处理字符序列的String类.String类在java.lang包中,由于java.lang包中的类被默认引入,因此程序可以直接使用S ...

  9. 20175215 2018-2019-2 第一周Linux虚拟机环境调试及java程序调试学习总结

    一.Linux虚拟机的java环境调试 之前直接在终端中使用export直接配置java的运行环境,导致每次终端被重启的时候都要重新配置java的运行环境,直到看到老师的博客Intellj IDEA ...

  10. windows怎么远程访问deepin linux桌面

    deepin linux端安装anydesk 1.首先点击打开任务栏上的“深度商店” 2.打开后搜索anydesk. 3.点击进入后按“安装”即可,安装完成即可在“深度商店”点击“打开”运行anyde ...