NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)
神tm比赛时多清个零就有60了T T
首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP。设f[i][j]表示比最短路多走i的长度,到j的方案数。
我们发现如果在最短路上的和零边会有后向性,怎么办呢?拓扑排序。
把最短路上的点和零边的点拉出来跑拓扑排序,如果有零环的话必定度数不为0,而且要注意零环必须在<=最短路+k的路径上才输出-1,这个就用刚刚跑出来的1起点到n起点的最短路来判断就好了。
然后先按拓扑序DP出i相同的,然后再DP不在最短路上或者零边的。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#define MOD(x) ((x)>=mod?(x)-mod:(x))
using namespace std;
const int maxn=;
struct tjm{int too, dis, pre;}e[][maxn];
struct poi{int x, dis;};
priority_queue<poi>q;
bool operator<(poi a, poi b){return a.dis>b.dis;}
int T, x, y, z, n, m, K, mod, top, tot[], ans;
int f[][maxn], dist[][maxn], last[][maxn], d[maxn], st[maxn];
void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y, int z, int ty){e[ty][++tot[ty]]=(tjm){y, z, last[ty][x]}; last[ty][x]=tot[ty];}
inline void dij(int x, int ty)
{
memset(dist[ty], , sizeof(dist[ty]));
dist[ty][x]=; q.push((poi){x, });
while(!q.empty())
{
poi now=q.top(); q.pop();
if(dist[ty][now.x]!=now.dis) continue;
for(int i=last[ty][now.x], too;i;i=e[ty][i].pre)
if(dist[ty][too=e[ty][i].too]>dist[ty][now.x]+e[ty][i].dis)
{
dist[ty][too]=dist[ty][now.x]+e[ty][i].dis;
q.push((poi){too, dist[ty][too]});
}
}
}
inline bool topo()
{
memset(d, , sizeof(d));
for(int i=;i<=n;i++)
for(int j=last[][i], too;j;j=e[][j].pre)
if(dist[][i]+e[][j].dis==dist[][too=e[][j].too]) d[too]++;
top=; for(int i=;i<=n;i++) if(!d[i]) st[++top]=i;
for(int i=;i<=top;i++)
for(int j=last[][st[i]], too;j;j=e[][j].pre)
if(dist[][st[i]]+e[][j].dis==dist[][too=e[][j].too])
{
d[too]--;
if(!d[too]) st[++top]=too;
}
for(int i=;i<=n;i++) if(d[i] && dist[][i]+dist[i][n]<=dist[][n]+K) return ;
return ;
}
int main()
{
read(T);
while(T--)
{
memset(last, , sizeof(last)); tot[]=tot[]=;
read(n); read(m); read(K); read(mod);
for(int i=;i<=m;i++) read(x), read(y), read(z), add(x, y, z, ), add(y, x, z, );
dij(, ); dij(n, );
if(!topo()) {puts("-1"); continue;}
memset(f, , sizeof(f)); f[][]=; ans=;
for(int i=;i<=K;i++)
{
for(int j=;j<=top;j++)
for(int k=last[][st[j]], too;k;k=e[][k].pre)
if(e[][k].dis+dist[][st[j]]==dist[][too=e[][k].too])
f[i][too]+=f[i][st[j]], f[i][too]=MOD(f[i][too]);
for(int j=;j<=n;j++)
for(int k=last[][j], too, tmp;k;k=e[][k].pre)
if((tmp=i+e[][k].dis+dist[][j]-dist[][too=e[][k].too])<=K && i!=tmp)
f[tmp][too]+=f[i][j], f[tmp][too]=MOD(f[tmp][too]);
ans+=f[i][n]; ans=MOD(ans);
}
printf("%d\n", ans);
}
}
NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)的更多相关文章
- [NOIP2017]逛公园 最短路+拓扑排序+dp
题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...
- [Luogu P3953] 逛公园 (最短路+拓扑排序+DP)
题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易 ...
- NOIP2017 Day1 T3 逛公园
NOIP2017 Day1 T3 更好的阅读体验 题目描述 策策同学特别喜欢逛公园.公园可以看成一张\(N\)个点\(M\)条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,\(N\)号点 ...
- 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP
[BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...
- 洛谷 3953 NOIP2017提高组Day1 T3 逛公园
[题解] 先建反向图,用dijkstra跑出每个点到n的最短距离dis[i] 设f[u][k]表示dis(u,n)<=mindis(u,n)+k的方案数.对于边e(u,v,w),走了这条边的话需 ...
- Luogu P3953 逛公园(最短路+记忆化搜索)
P3953 逛公园 题面 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园的入口,\(N\) 号点是公 ...
- BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP
BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP Description 受到秘鲁的马丘比丘的新式水上乐园的启发,Farmer John决定也为奶牛们建 一个水上乐园. ...
- POJ 3249 拓扑排序+DP
貌似是道水题.TLE了几次.把所有的输入输出改成scanf 和 printf ,有吧队列改成了数组模拟.然后就AC 了.2333333.... Description: MR.DOG 在找工作的过程中 ...
- 洛谷P3244 落忆枫音 [HNOI2015] 拓扑排序+dp
正解:拓扑排序+dp 解题报告: 传送门 我好暴躁昂,,,怎么感觉HNOI每年总有那么几道题题面巨长啊,,,语文不好真是太心痛辣QAQ 所以还是要简述一下题意,,,就是说,本来是有一个DAG,然后后来 ...
随机推荐
- Django的简介
一.MTV模型 Django的MTV模式: Model(模型):和数据库相关的.负责业务对象与数据库的对象(ORM) Template(,模板):放所有的HTML文件 模板语法:目的是将变量(数据库内 ...
- JMeter自学笔记1-环境安装
一.写在前面的话: Jmeter是一款优秀的开源测试工具, 是每位测试工程师进阶过程中,需要熟悉并掌握的一款测试工具,熟练使用Jmeter能大大提高工作效率. Jmeter环境安装需要依赖JDK,所以 ...
- Linux 安装FastDFS<准备>(使用Mac远程访问)
阅读本文需要一定的Linux基础 一 FastDFS简介 fastdfs是用c语言编写的一款开源分布式文件系统, fastdfs为互联网量身定制, 充分考虑了冗余备份, 负载均衡, 线性扩容等机制, ...
- JavaFX 学习笔记——jfoenix类库学习——raised风格按钮创建
创建按钮 JFXButton jfxb = new JFXButton("hello"); jfxb.getStyleClass().add("button-raised ...
- socket编程为什么需要htonl(), ntohl(), ntohs(),htons() 函数-------转载
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题.这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数. 网络字节顺序与本地字节顺序之间的转 ...
- 经典教程|10 分钟速成 Python3
Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计. 它是如今最常用的编程语言之一.它的语法简洁且优美,几乎就是可执行的伪代码. 注意:这篇教程是基于 Pyth ...
- 136.只出现一次的数字 leetcode ^运算符 JavaScript解法
leetcode上的一道题简单题 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间 ...
- Redis5.0:现公测全免费,点击就送,注册账号,即开即用
华为云分布式缓存服务Redis,是华为云服务的一款核心产品. 分布式缓存Redis是一款内存数据库服务,基于双机热备的高可用架构,提供单机.主从.集群等丰富类型的缓存类型. 现推出最新版本Redis5 ...
- 【ZABBIX】SNMPtrap实现主动监控的原理与安装配置
工欲善其事,必先利其器.作为一款强大的开源软件,Zabbix号称“Monitor Everything”,其所依赖的,很大程度上便是SNMP的数据采集支持.SNMP 协议是用来管理设备的协议,目前SN ...
- 广东ACM省赛 E题
题意: 输入一个P 使得存在一个一个N大于等于P, 并且存在m 等于 m/n * (m-1)/(n-1)=1/2. 思路 此题可以利用佩尔方程求解, 也可以打表解决.本次我解决利用的是佩尔方程(其实也 ...