题意

题目链接

Sol

去年考NOIP的时候我好像连最短路计数都不会啊qwq。。

首先不难想到一个思路,\(f[i][j]\)表示到第\(i\)个节点,与最短路之差长度为\(j\)的路径的方案数

首先把每个节点的最短路求出来

转移的时候按拓扑序(也就是按距离从小到大排序)转移一下

然而有\(0\)边的时候会挂掉,原因是会有dis相同的时候,这时候单按dis排序会无法判断转移方向

一种方案是直接把所有\(0\)边加入到新图中,拓扑排序一遍。得到第二关键字

同时判断一下\(0\)环

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP make_pair
#define fi first
#define se second
using namespace std;
const int MAXN = 100001, INF = 1e9 + 7;
inline int read() {char c = getchar(); int x = 0, f = 1;while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x * f;
}
int T, N, M, K, mod, f[MAXN][51], dis1[MAXN], disn[MAXN], vis[MAXN], inder[MAXN], id[MAXN];
vector<Pair> v[MAXN], rv[MAXN];
vector<pair<pair<int, int>, int> > P;
vector<int> E[MAXN];
void init() {memset(f, 0, sizeof(f));memset(inder, 0, sizeof(inder));P.clear();f[1][0] = 1;N = read(); M = read(); K = read(); mod = read();for(int i = 1; i <= N; i++) v[i].clear(), E[i].clear();for(int i = 1; i <= M; i++) {int x = read(), y = read(), z = read();v[x].push_back(MP(y, z)); rv[y].push_back(MP(x, z));if(!z) E[x].push_back(y), inder[y]++;}
}
void add(int &x, int y) {if(x + y < 0) x = (x + y + mod);else x = (x + y >= mod ? x + y - mod : x + y);
}
int Topsort() {int cnt = 0; queue<int> q;for(int i = 1; i <= N; i++) if(!inder[i]) id[i] = ++cnt, q.push(i);while(!q.empty()) {int p = q.front(); q.pop();for(int i = 0, to; i < E[p].size(); i++) if(!(--inder[to = E[p][i]])) q.push(to), id[to] = ++cnt;}for(int i = 1; i <= N; i++) if(inder[i] && (dis1[i] + disn[i] <= dis1[N] + K)) return -1;return 0;
}
void Dij(int bg, int *dis) {priority_queue<Pair> q; q.push(MP(0, bg)); memset(vis, 0, sizeof(vis));for(int i = 1; i <= N; i++) dis[i] = INF + 1; dis[bg] = 0;while(!q.empty()) {if(vis[q.top().se]) {q.pop(); continue;}int p = q.top().se; q.pop(); vis[p] = 1;if(bg == 1) {for(int i = 0, to; i < v[p].size(); i++) if(dis[to = v[p][i].fi] > dis[p] + v[p][i].se) dis[to] = dis[p] + v[p][i].se, q.push(MP(-dis[to], to));            } else {for(int i = 0, to; i < rv[p].size(); i++) if(dis[to = rv[p][i].fi] > dis[p] + rv[p][i].se) dis[to] = dis[p] + rv[p][i].se, q.push(MP(-dis[to], to));           }}
}
int solve() {Dij(1, dis1);Dij(N, disn);if(Topsort() == -1) return -1;for(int i = 1; i <= N; i++) P.push_back(MP(MP(dis1[i], id[i]), i));sort(P.begin(), P.end());f[1][0] = 1;for(int j = 0; j <= K; j++) {for(int i = 0; i < N; i++) {int x = P[i].se;for(int k = 0; k < v[x].size(); k++) {int to = v[x][k].fi, w = v[x][k].se, ps = dis1[x] + j + w - dis1[to];if(ps <= K) add(f[to][ps], f[x][j]);}}}int ans = 0;for(int i = 0; i <= K; i++) add(ans, f[N][i]);return ans;
}
int main() {T = read(); while(T--) {init();printf("%d\n", solve());            }return 0;
}
/*
*/

洛谷P3953 逛公园(dp 拓扑排序)相关推荐

  1. 洛谷P3953 逛公园

    DP+图论大毒瘤. 推荐这个博客. 先跑两遍最短路,搞掉一些无用点. 然后选出最短路上的边,做拓扑排序. 然后每层DP. 具体看代码. 用到的数组较多,记得清空. 1 #include <cst ...

  2. 洛谷 P3953 逛公园

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

  3. NOIP2017洛谷P3953:逛公园(分层图最短路、dp、拓扑)

    解析 容易想到dp 先跑一遍最短路把每个点的dis求出来 设计dpu,xdp_{u,x}dpu,x​表示结点u多走了x的方案数 dp按照dis升序排列后,从前到后转移即可 如果有0边,求出只有0边时的 ...

  4. 2018.11.02 洛谷P2661 信息传递(拓扑排序+搜索)

    传送门 按照题意模拟就行了. 先拓扑排序去掉不在环上面的点. 剩下的都是简单环了. 于是都dfsdfsdfs一遍求出最短的环就行. 代码: #include<bits/stdc++.h> ...

  5. 洛谷 P1983 车站分级(拓扑排序)

    https://www.luogu.com.cn/problem/P1983 思路 对于每一趟车,将其经过的车站中,停靠的和不停靠的连一条边,注意边的去重,要双向标记,不然有个点会超时,这样拓扑排序递 ...

  6. 洛谷P1983 车站分级(拓扑排序)

    [题目描述] 一条单向的铁路线上,依次有编号为 1 , 2 , - , n 1,2,\dots ,n 1,2,-,n的 n n n个火车站.每个火车站都有一个级别,最低为 1 1 1级.现有若干趟车次 ...

  7. 洛谷P3243 [HNOI2015]菜肴制作——拓扑排序

    题目:https://www.luogu.org/problemnew/show/P3243 正向按字典序拓扑排序很容易发现是不对的,因为并不是序号小的一定先做: 但若让序号大的尽可能放在后面,则不会 ...

  8. 洛谷--橙色百道DP总结

    最近刷完了洛谷橙色DP大约一百道,算是发现了一些套路,就部分题目做一些总结. 大概分为三类 第一类,九大背包及其衍生 第二类,经典DP模型,如LCS,LIS等 第三类,实际问题背景的普通,环形,树上D ...

  9. 洛谷 P1638 逛画展

    洛谷 P1638 逛画展 题目链接 题目描述 博览馆正在展出由世上最佳的 M 位画家所画的图画. wangjy想到博览馆去看这几位大师的作品. 可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必 ...

最新文章

  1. 揭秘@爱可可:“寂寞呆子”成长记
  2. 解决response响应乱码
  3. 斯坦福大学Christopher Manning:Transformer语言模型为什么能取得突破
  4. leetcode 128. Longest Consecutive Sequence | 128. 最长连续序列(Java)
  5. python方法items_Python字典items()方法与示例
  6. Windows系统内置彩蛋
  7. 别@微信官方了,最全的圣诞帽都在这儿了!
  8. CH340G USB转串口接口定义
  9. 医患诚信系统——软件项目的风险
  10. 微信小程序开发一个多少钱
  11. unity3d学习笔记(一)方向键移动物体
  12. Vue 内嵌微信登录二维码及修改默认样式
  13. 深入理解iOS APP启动过程
  14. SOAP UI工具填写用户名密码校验通不过,需要报文头添加
  15. HTML小游戏12 —— 汽车赛道飙车游戏(附完整源码)
  16. 关于代码复制到IDEA上空格变成`NBSP`的解决办法
  17. Email开发初步总结
  18. badminton ball
  19. 轿车优劣评说 1/2 ,全文超过1万字,请慢慢看。
  20. java中等效encodeuri_encodeURI来解决URL传递时的中文问题

热门文章

  1. SAP SD之如何配置发票分割开票
  2. 计算机视觉的基本概念
  3. 线性回归模型原理及推导
  4. 挑战者联盟!谁会成为最赚钱的人工智能公司
  5. 【机器学习基本理论】详解最大后验概率估计(MAP)的理解
  6. 为什么大家都不戳破深度学习的本质?!
  7. Tensorflow—CNN应用于MNIST数据集分类
  8. 信息大脑如何从物理大脑中涌现?
  9. 机载雷达发展简史:从蝙蝠到机载相控阵
  10. 自动驾驶又陷“派系”之争:该约束行人还是让车更完美