【NOIP2017提高组正式赛】Day1T3逛公园

2023-12-05 13:30

本文主要是介绍【NOIP2017提高组正式赛】Day1T3逛公园,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

   策策同学特别喜欢逛公园。公园可以看成一张o个点n条边构成的有向图,且没有自环和重边。其中1号点是公园的入口,o号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。策策每天都会去逛公园,他总是从1号点进去,从o号点出来。策策喜欢新鲜的事物,他不希望有两天逛公园的路线完全一样,同时策策还是一个特别热爱学习的好孩子,他不希望每天在逛公园这件事上花费太多的时间。如果1号点到o号点的最短路长为e,那么策策只会喜欢长度不超过e + k的路线。策策同学想知道总共有多少条满足条件的路线,你能帮帮他吗?为避免输出过大,答案对p取模。如果有无穷多条合法的路线,请输出−1。

Input

输入文件名为 park.in 。
第一行包含一个整数 T, 代表数据组数。
接下来T组数据,对于每组数据:
第一行包含四个整数 O,N,K,P,每两个整数之间用一个空格隔开。
接下来N行,每行三个整数, 代表编号为的点之间有一条权值为 的有向边,每两个整数之间用一个空格隔开。
Output
输出文件包含 T行,每行一个整数代表答案。

Sample Input

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

Sample Output

3
-1

样例说明:
对于第一组数据,最短路为 3。
1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5 为 3 条合法路径。

数据范围

这里写图片描述

题解

求最短路是很简单的,
如果只求最短路的路径数也是很简单的,
fi 表示从点1到点i的最短路路径条数,
转移的时候就判断当前边是不是在最短路上面,是就转移。

现在要求比最短路大k的,
很自然地想到设多一维,
fj,i 表示比当前最短路大j,到达点i的路径数。

关于转移,就有所不同了,
要用拓扑序,而且要先枚举比最短路大多少,

对于有无穷解的情况,就是存在一个权值为0的环在最短路上面。

code

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define ll long long
#define N 100003
#define inf 1125899906842624
using namespace std;char ch;
void read(int& n)
{n=0;for(ch=getchar();ch<'0' || ch>'9';ch=getchar());for(;'0'<=ch && ch<='9';n=(n<<3)+(n<<1)+ch-48,ch=getchar());
}int nxt[N*2],to[N*2],last[N*2],tot;
int nxt1[N*2],to1[N*2],last1[N*2],tot1;
int nxt2[N*2],to2[N*2],last2[N*2],tot2,g[N];
ll v[N*2],v1[N*2],dis[N],dis1[N];
int T,n,m,k,p,x,y,z;
int d[N*200],head,tail;
ll f[53][N],ans;
bool bz[N],check;void ins(int x,int y,int z)
{nxt[++tot]=last[x];to[tot]=y;v[tot]=z;last[x]=tot;
}void ins1(int x,int y,int z)
{nxt1[++tot1]=last1[x];to1[tot1]=y;v1[tot1]=z;last1[x]=tot1;
}void ins2(int x,int y)
{nxt2[++tot2]=last2[x];to2[tot2]=y;last2[x]=tot2;g[y]++;
}void spfa()
{memset(bz,1,sizeof(bz));memset(dis,127,sizeof(dis));dis[tail=1]=bz[d[1]=1]=head=0;while(head<tail){x=d[++head];for(int i=last[x];i;i=nxt[i])if(dis[x]+v[i]<dis[to[i]]){dis[to[i]]=dis[x]+v[i];if(bz[to[i]]){bz[to[i]]=0;d[++tail]=to[i];}}bz[x]=1;}
}void spfa1()
{memset(bz,1,sizeof(bz));memset(dis1,127,sizeof(dis1));dis1[d[tail=1]=n]=bz[n]=head=0;while(head<tail){x=d[++head];for(int i=last1[x];i;i=nxt1[i])if(dis1[x]+v1[i]<dis1[to1[i]]){dis1[to1[i]]=dis1[x]+v1[i];if(bz[to1[i]]){bz[to1[i]]=0;d[++tail]=to1[i];}}bz[x]=1;}
}void pre()
{head=tail=0;for(int i=1;i<=n;i++)if(g[i]==0)d[++tail]=i;while(head<tail){x=d[++head];for(int i=last2[x];i;i=nxt2[i])if(--g[to2[i]]==0)d[++tail]=to2[i];}
}void add(ll& x,ll y)
{x=y+x>p?y+x-p:y+x;
}int main()
{freopen("park.in","r",stdin);freopen("park.out","w",stdout);read(T);while(T--){read(n);read(m);read(k);read(p);memset(last,0,sizeof(last)); memset(last1,0,sizeof(last1));  memset(last2,0,sizeof(last2)); memset(g,0,sizeof(g));ans=tot=tot1=tot2=0;for(int i=1;i<=m;i++)read(x),read(y),read(z),ins(x,y,z),ins1(y,x,z);spfa();spfa1();for(int i=1;i<=n;i++)for(int j=last[i];j;j=nxt[j])if(dis[i]+v[j]==dis[to[j]])ins2(i,to[j]);pre();check=0;for(int i=1;i<=n;i++)if(g[i] && dis[i]+dis1[i]<=dis[n]+k){check=1;break;}if(check){printf("-1\n");continue;}memset(f,0,sizeof(f));f[0][1]=1;for(int i=0;i<=k;i++)for(int j=1;j<=tail;j++){x=d[j];if(dis[x]>inf || dis1[x]>inf)continue;if(dis[x]+dis1[x]+i>dis[n]+k)continue;for(int p=last[x];p;p=nxt[p]){ll t=dis[x]+v[p]+i-dis[to[p]];if(t<=k)add(f[t][to[p]],f[i][x]);}}ans=0;for(int i=0;i<=k;i++)add(ans,f[i][n]);printf("%lld\n",ans);}return 0;
}

这篇关于【NOIP2017提高组正式赛】Day1T3逛公园的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/457750

相关文章

键盘快捷键:提高工作效率与电脑操作的利器

键盘快捷键:提高工作效率与电脑操作的利器 在数字化时代,键盘快捷键成为了提高工作效率和优化电脑操作的重要工具。无论是日常办公、图像编辑、编程开发,还是游戏娱乐,掌握键盘快捷键都能带来极大的便利。本文将详细介绍键盘快捷键的概念、重要性、以及在不同应用场景中的具体应用。 什么是键盘快捷键? 键盘快捷键,也称为热键或快捷键,是指通过按下键盘上的一组键来完成特定命令或操作的方式。这些快捷键通常涉及同

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

如何提高 GitHub 的下载速度

如何提高 GitHub 的下载速度 文章目录 如何提高 GitHub 的下载速度1. 注册账号2. 准备好链接3. 创建仓库4. 在码云上下载代码5. 仓库更新了怎么办 一般来说,国内的朋友从 GitHub 上面下载代码,速度最大是 20KB/s,这种龟速,谁能忍受呢? 本文介绍一种方法——利用“码云”,可以大大提高下载速度,亲测有效。 1. 注册账号 去“码云”注册一

微软正式推出 Spartan 斯巴达浏览器

作为用于替代 IE 浏览器的下一代继任者,微软的 Project Spartan 斯巴达浏览器可算是吊足了玩家们的胃口!如今,在最新的 Windows 10 Build 10049 版本起,它终于正式登场了。 斯巴达浏览器搭载了全新的渲染引擎、新的用户界面并集成了 Cortana 语音助手。功能上新增了稍后阅读列表、阅读视图、F12开发者工具、支持网页注释 (手写涂鸦),可以保存到 O

如何提高开发的效率,让老板不知所措的给你发工资

设计模式 UML JSP 编程 数据结构 1.你可能会常常发现,写了一段代码后,编译程序时是一大堆的出错 (原因:语法不熟)  ──别担心,这是每个程序员必须经历的事,这时候你就需要更大的耐心及细心,对每一行代码进行仔细人阅读并改正,这个很重要,这可以培养你的理解代码能力,所以要常读程序,不要等到程序运行以后才知道你的程序的结果。  ──如何避免:在写代码以前,要认真的学习计算机语

Java开发实例大全提高篇——Applet的应用

开发十年,就只剩下这套架构体系了! >>>    第21章  Applet的应用 21.1  Applet在html中的使用 实例549  在html中显示Applet HtmlShowApplet.java     public void paint(Graphics g){         g.drawString("html文件已经运行", 50, 50);// 绘制文本

Java开发实例大全提高篇——Java安全

开发十年,就只剩下这套架构体系了! >>>    第6篇  Java安全与Applet应用篇 第20章  Java安全 20.1  Java对称加密 实例531  使用BASE64加密     public static String encryptBASE64(byte[] data) {         //加密数据         return (new BASE64Encoder()

2024国赛论文拿奖快对照这几点及评阅要点,勿踩雷区!(国赛最后冲刺,提高获奖概率)

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 2024“高教社杯”全国大学生数学建模竞赛已过去第三个夜晚,小伙伴们都累了没有,如果感到思维滞涩,别忘了稍作休息,放松一下自己,准备迎接国赛非常重要的收尾阶段——论文。 国赛这几天的努力最后都

C++提高编程三(vector容器、deque容器)

文章目录 vector容器vector赋值操作vector容量和大小vector插入和删除vector数据存取vector互换容器vector预留空间deque容器构造函数deque赋值操作deque大小操作deque 插入和删除deque 数据存取deque 排序 vector容器 vector容器数据结构和数组相似,也称为单端数组。区别在于数组是静态空间,vector可以

Open Source, Open Life 第九届中国开源年会论坛征集正式启动

中国开源年会 COSCon 是业界最具影响力的开源盛会之一,由开源社在2015年首次发起,而今年我们将迎来第九届 COSCon! 以其独特定位及日益增加的影响力,COSCon 吸引了越来越多的国内外企业、高校、开源组织/社区的大力支持。与一般企业、IT 媒体、行业协会举办的行业大会不同,COSCon 具有跨组织、跨项目、跨社区的广泛覆盖面,也吸引了众多国内外开源开发者和开源爱好者的关注及参与