[NOIP2017]逛公园 最短路+拓扑排序+dp
题目描述
给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数。求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 $-1$ 。
输入
第一行包含一个整数 $T$ , 代表数据组数。
接下来 $T$ 组数据,对于每组数据: 第一行包含四个整数 $N,M,K,P$ ,每两个整数之间用一个空格隔开。
接下来 $M$ 行,每行三个整数 $a_i,b_i,c_i$ ,代表编号为 $a_i,b_i$ 的点之间有一条权值为 $c_i$ 的有向边,每两个整数之间用一个空格隔开。
输出
输出文件包含 $T$ 行,每行一个整数表示答案。
样例输入
2
5 7 2 10
1 2 1
2 4 0
4 5 2
2 3 2
3 4 1
3 5 2
1 5 3
2 2 0 10
1 2 0
2 1 0
样例输出
3
-1
题解
最短路+拓扑排序+dp
首先使用堆优化Dijkstra或Spfa(不知道本题是否会卡)求出1到所有点的最短路。
由于对于所有边 $(x,y,z)$ 满足 $dis[x]+z\ge dis[y]$ ,因此超过最短路的部分不会减少。
那么我们设 $f[i][j]$ 表示到达点 $i$ 时经过的路径总长度为 $dis[i]+j\ (j \le k)$ 的方案数。那么这相当于一个新的分层图,只会在同层或向上层转移,不会像下层转移。
这就转化为图上求路径条数。首先初始化 $f[1][0]=0 $ ,跑拓扑排序的同时进行转移。
如果一个点被排到了,那么 $f$ 值即为路径条数。
如果一个点没有被排到,则说明有环连接到它,即路径条数为 $\infty$。
因此把所有 $f[n][0...k]$ 统计一下即可。
时间复杂度 $O(T(m\log n+mk))$
考场上一眼看出题解,然而卡了两个小时的常数才勉强卡进去...
考场原代码(去掉了文件操作):
#include <queue>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
#define M 200010
#define R register
#define pos(x , y) (x + (y) * n)
using namespace std;
typedef pair<int , int> pr;
priority_queue<pr> q;
int head[N] , to[M] , len[M] , next[M] , cnt , dis[N] , vis[N];
int ll[N * 51] , rr[N * 51] , tt[M * 51] , que[N * 51] , ind[N * 51] , f[N * 51];
inline void add(int x , int y , int z)
{
to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
inline char nc()
{
static char buf[100000] , *p1 , *p2;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
inline int read()
{
int ret = 0; char ch = nc();
while(!isdigit(ch)) ch = nc();
while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc();
return ret;
}
int main()
{
int T = read();
while(T -- )
{
memset(head , 0 , sizeof(head));
memset(vis , 0 , sizeof(vis));
memset(ind , 0 , sizeof(ind));
memset(f , 0 , sizeof(f));
cnt = 0;
int n = read() , m = read() , k = read() , z , ans = 0 , flag = 1;
R int p = read() , i , j , x , y , l = 1 , r = 0;
for(i = 1 ; i <= m ; ++i) x = read() , y = read() , z = read() , add(x , y , z);
memset(dis , 0x3f , sizeof(dis));
dis[1] = 0 , q.push(pr(0 , 1));
while(!q.empty())
{
x = q.top().second , q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(i = head[x] ; i ; i = next[i])
if(dis[to[i]] > dis[x] + len[i])
dis[to[i]] = dis[x] + len[i] , q.push(pr(-dis[to[i]] , to[i]));
}
cnt = 0;
for(x = 1 ; x <= n ; ++x)
{
for(j = 0 ; j <= k ; ++j)
{
ll[pos(x , j)] = cnt + 1;
for(i = head[x] ; i ; i = next[i])
if(j + dis[x] + len[i] - dis[to[i]] <= k)
++ind[tt[++cnt] = pos(to[i] , j + dis[x] + len[i] - dis[to[i]])];
rr[pos(x , j)] = cnt;
}
}
f[1] = 1;
for(x = 1 ; x <= pos(n , k) ; ++x)
if(!ind[x])
que[++r] = x;
while(l <= r)
{
x = que[l ++ ];
for(i = ll[x] ; i <= rr[x] ; ++i)
{
y = tt[i];
f[y] += f[x] , ind[y] -- ;
if(f[y] >= p) f[y] -= p;
if(!ind[y]) que[++r] = y;
}
}
for(i = 0 ; i <= k ; ++i)
{
if(ind[pos(n , i)]) flag = 0;
ans = (ans + f[pos(n , i)]) % p;
}
if(flag) printf("%d\n" , ans);
else puts("-1");
}
return 0;
}
[NOIP2017]逛公园 最短路+拓扑排序+dp的更多相关文章
- [Luogu P3953] 逛公园 (最短路+拓扑排序+DP)
题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易 ...
- 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP
[BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...
- NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)
神tm比赛时多清个零就有60了T T 首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP.设f[i][j]表示比最短路多走i的长度,到j的方案数. 我们发现如果在最短路上的和零边会有后向性, ...
- [NOIP2017]逛公园 最短路图 拓扑序DP
---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...
- [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)
题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...
- 【题解】NOIP2017逛公园(DP)
[题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...
- 【比赛】NOIP2017 逛公园
考试的时候灵光一闪,瞬间推出DP方程,但是不知道怎么判-1,然后?然后就炸了. 后来发现,我只要把拓扑和DP分开,中间加一个判断,就AC了,可惜. 看这道题,我们首先来想有哪些情况是-1:只要有零环在 ...
- [NOIP2017] 逛公园
[NOIP2017] 逛公园 题目大意: 给定一张图,询问长度 不超过1到n的最短路长度加k 的1到n的路径 有多少条. 数据范围: 点数\(n \le 10^5\) ,边数\(m \le 2*10^ ...
- BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP
BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP Description 受到秘鲁的马丘比丘的新式水上乐园的启发,Farmer John决定也为奶牛们建 一个水上乐园. ...
随机推荐
- JavaScript内置对象——Math对象
这几天在刷leetcode的时候用到了一些Math对象的知识,故作一下总结~ JavaScript中的Math对象也是一个常见的内置对象,然而与String等其它常见对象不同,Math对象没有构造函数 ...
- python高级编程读书笔记(一)
python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...
- #ifndef详解
#ifndef 是"if not defined"的简写,是预处理功能(宏定义.文件包含.条件编译)当中的条件编译,可以根据是否已经定义了一个变量来进行分支选择,其作用是: 1.防 ...
- plsql developer日期类型数据格式不对如何设置?
当把一个数据库中的数据复制到另一个数据库时,如果数据中包含日期类型,会提示数据格式不正确.或者两个plsql developer设置不同,但实际上建表语句一样. 此时可在plsql中做如下设置: 首选 ...
- tomcat端口冲突,多个tomcat同时启动问题
一台PC机上安装了两个tomcat,需要同时启动,每个tomcat上跑一个程序,但是现在提示端口号冲突,需要手动更改. 需要修改/conf/server.xml四个地方: 1.<Server p ...
- windows系统下安装tomcat及配置
1.安装测试 1.安装 推荐使用免安装版的Tomcat(放在没有中文和空格的目录下),前提是已经安装了JDK并配置了环境变量. 2.测试 双击startup.bat,浏览器输入url:localhos ...
- zabbix3.0.4导入中文模板后乱码问题处理
通过yum安装方式部署了zabbix3.0.4监控服务器,配置过程中发现当导入的模板中有中文时,图中的中文会变成方块 如下图所示: 这个问题是由于zabbix的web端没有中文字库,我们最需要把中文字 ...
- Dotfuscator使用
参考:https://www.cnblogs.com/xiezunxu/articles/7228741.html
- windows下升级node&npm
一.升级npm npm install -g npm 二.升级node 1.查询node的安装目录 where node 2.在官网下载最新的安装包,直接覆盖安装即可. https://nodejs. ...
- OneNET麒麟座应用开发之九:与SD卡通讯并保存数据
由于需要记录的数据量比较大,而且有些时候,有的用户不方便实时上传数据,所以要求使用SD卡存储数据然后人工收取上传.为此我们选择了一种通用的SD卡读写器. 1.读卡器简介 该读卡器整合 SD 卡规范和 ...