【NOIP 2017 提高组】逛公园
【题目】
传送门
题目描述:
策策同学特别喜欢逛公园。公园可以看成一张 nnn 个点 mmm 条边构成的有向图,且没有自环和重边。其中 111 号点是公园的入口,nnn 号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。
策策每天都会去逛公园,他总是从 111 号点进去,从 nnn 号点出来。
策策喜欢新鲜的事物,他不希望有两天逛公园的路线完全一样,同时策策还是一个特别热爱学习的好孩子,他不希望每天在逛公园这件事上花费太多的时间。如果 111 号点到 nnn 号点的最短路长为 ddd,那么策策只会喜欢长度不超过 d+kd+kd+k 的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮他吗?
为避免输出过大,答案对 ppp 取模。
如果有无穷多条合法的路线,请输出 −1-1−1 。
输入格式:
第一行包含一个整数 ttt,代表数据组数。
接下来 ttt 组数据,对于每组数据:
第一行包含四个整数 nnn,mmm,kkk,ppp,每两个整数之间用一个空格隔开。
接下来 mmm 行,每行三个整数 aia_iai,bib_ibi,cic_ici,代表编号为 aia_iai,bib_ibi 的点之间有一条权值为 cic_ici 的有向边,每两个整数之间用一个空格隔开。
输出格式:
输出文件包含 ttt 行,每行一个整数代表答案。
样例数据:
输入
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
备注:
【输入输出样例1说明】
对于第一组数据,最短路为 333 。
1−51-51−5,1−2−4−51-2-4-51−2−4−5,1−2−3−51-2-3-51−2−3−5 为 333 条合法路径。
【数据规模与约定】
对于不同的测试点,我们约定各种参数的规模不会超过如下
对于 100%100\%100% 的数据,1≤p≤1091≤p≤10^91≤p≤109;1≤ai,bi≤n1≤a_i,b_i≤n1≤ai,bi≤n;0≤ci≤10000≤c_i≤10000≤ci≤1000。
数据保证:至少存在一条合法的路线。
【分析】
30  pts(k=0)30\; pts(k=0)30pts(k=0):
这部分的分应该是比较容易得到的吧
k=0k=0k=0,转换一下题目意思就是统计最短路个数,由于 k=0k=0k=0 是没有 000 边的,所以还不用判断是否有无穷中路线
不过要注意的是一定要有 visvisvis 数组啊,不然会重复计算的,就错了(被坑了无数次了)
70  pts(70\;pts(70pts(没有 000 边))):
这一部分分是用 dpdpdp 来做的
首先肯定还是要求最短路(这应该是废话)
定义 dis[i]dis[i]dis[i] 为 111 到 iii 的最短路,f[i][j]f[i][j]f[i][j] 为比 dis[i]dis[i]dis[i] 多 jjj 的方案数
现在考虑怎么转移,假如现在 kkk 可以到 iii,边权为 www,并且是从 f[k][x]f[k][x]f[k][x] 转移到 f[i][j]f[i][j]f[i][j]
那么容易得到 x+dis[k]+w−dis[i]=jx+dis[k]+w-dis[i]=jx+dis[k]+w−dis[i]=j,移项得 x=dis[i]−dis[k]+j−wx=dis[i]-dis[k]+j-wx=dis[i]−dis[k]+j−w,那方程就是:
f[i][j]=∑f[k][dis[i]−dis[k]+j−w]f[i][j]=\sum f[k][dis[i]-dis[k]+j-w]f[i][j]=∑f[k][dis[i]−dis[k]+j−w]
(当然如果发现 dis[i]−dis[k]+j−w<0dis[i]-dis[k]+j-w<0dis[i]−dis[k]+j−w<0 了直接跳过就好了)
实际操作的时候用记忆化搜索实现就可以了
100  pts100\;pts100pts:
现在考虑加上 000 边该怎么办
其实也比较简单,只用再记录一个 vis[i][j]vis[i][j]vis[i][j] 表示 f[i][j]f[i][j]f[i][j] 这个状态出现过没有
如果存在环,从 iii 开始搜索的话(状态是 f[i][j]f[i][j]f[i][j]),就会再次搜到 iii(注意是搜索到 iii,不是回溯到 iii)
那么假设这个环上的其他点为 p1,p2,...,pxp_1,p_2,...,p_xp1,p2,...,px,边权为 w1,w2,...,wxw_1,w_2,...,w_xw1,w2,...,wx,假如回到 iii 的状态依旧是 f[i][j]f[i][j]f[i][j],就说明 w1+w2+...+wx=0w_1+w_2+...+w_x=0w1+w2+...+wx=0(disdisdis 会互相抵消掉),就是 000 环,这时就输出 −1-1−1
【代码】
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define K 55
#define N 100005
#define M 500005
using namespace std;
int n,m,k,p,t1,t2,flag;
int d[N],f[N][K],vis[N][K];
int first[N],v[M],w[M],nxt[M];
int First[N],V[M],W[M],Nxt[M];
priority_queue<pair<int,int> >q;
void add(int x,int y,int z) {nxt[++t1]=first[x];first[x]=t1;v[t1]=y;w[t1]=z;}
void Add(int x,int y,int z) {Nxt[++t2]=First[x];First[x]=t2;V[t2]=y;W[t2]=z;}
void init()
{t1=t2=flag=0;memset(f,-1,sizeof(f));memset(first,0,sizeof(first));memset(First,0,sizeof(First));
}
void dijkstra(int s)
{int x,y,i;memset(d,127/3,sizeof(d));q.push(make_pair(0,s));d[s]=0;while(!q.empty()){x=q.top().second;q.pop();for(i=first[x];i;i=nxt[i]){y=v[i];if(d[y]>d[x]+w[i]){d[y]=d[x]+w[i];q.push(make_pair(-d[y],y));}}}
}
int dfs(int now,int val)
{if(~f[now][val]) return f[now][val];int i,to,num;f[now][val]=0,vis[now][val]=1;for(i=First[now];i;i=Nxt[i]){to=V[i];num=d[now]-d[to]+val-W[i];if(num<0) continue;if(vis[to][num]) flag=1;f[now][val]=(f[now][val]+dfs(to,num))%p;}vis[now][val]=0;return f[now][val];
}
int main()
{int x,y,z,i,T;scanf("%d",&T);while(T--){init();scanf("%d%d%d%d",&n,&m,&k,&p);for(i=1;i<=m;++i){scanf("%d%d%d",&x,&y,&z);add(x,y,z),Add(y,x,z);}int ans=0;dijkstra(1);for(i=0;i<=k;++i) dfs(n,i);if(flag) {puts("-1");continue;}memset(f,-1,sizeof(f));f[1][0]=1;for(i=0;i<=k;++i)ans=(ans+dfs(n,i))%p;printf("%d\n",ans);}return 0;
}
【NOIP 2017 提高组】逛公园相关推荐
- 洛谷 P3953 [NOIP2017 提高组] 逛公园
开始刷题单啦~,这部分的洛谷好题作为个人训练记录和以后复习用,有兴趣的可以一起做做 题目链接:P3953 [NOIP2017 提高组] 逛公园 题意都是中文就不翻译了 题解:这是一道记忆化+搜索的题目 ...
- NOIP 2017 提高组 初赛
NOIP 2017 提高组 初赛 做题感悟. 五.完善程序,是本张试卷最简单的题目,两道题做完,大约花了10分钟.2017-10-17 18:25 对了答案,破天荒,全对. 1.(大整数除法) 有如下 ...
- NOIP 2017 提高组 K: 奶酪 (SPFA || 并查集)
K: 奶酪 时间限制: 1 Sec 内存限制: 128 MB 提交: 115 解决: 30 [提交][状态][讨论版] 题目描述 现有一块大奶酪,它的高度为 h ,它的长度和宽度我们可以认为是无限 ...
- 【NOIP 2017 提高组 DAY1 T1】小凯的疑惑
emmm貌似过不了多久就要去考NOIP了,于是我终于开始刷往年的题了 [题目] 题目描述: 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有无数个.在不找零的情况下,仅凭这两种 ...
- NOIP 2018提高组复赛C/C++试题及答案详解
NOIP 2018提高组历年真题 CCF NOIP2018 初赛提高组 C++语言试题 第 1 页,共9 页 第二十四届全国青少年信息学奥林匹克联赛初赛 提高组 C++语言试题 竞赛时间:2018 年 ...
- [NOIP 2013提高组]转圈游戏 题解
这题在洛谷上是道黄题,即[普及/提高-] 所以虽然是提高组的,但是其实挺简单的. 我们来看下题面: [NOIP 2013]转圈游戏 刚看到题面作为一个蒟蒻感觉它都不配做黄题,但是直到我看清楚了后发现它 ...
- NOIP 2013 提高组 货车运输
描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...
- NOIP 2008 提高组 复赛 message 传字条
NOIP 2008 提高组 复赛 message 传字条 1.样例很快模拟成功,但感觉是凑出来的,没有章法. 2.深度优先遍历,但感觉容易超时. 3.动态规划?翻看他人代码,发现动态规划的写法,确实想 ...
- NOIP 2015 提高组 初赛
NOIP 2015 提高组 初赛 疑难点 学习 感悟. 一. 3. 示例如下(来自自个的理解): 101.101 十进制 转十进制1*10^2+0*10^1+1*10^0+1*10^-1+0*10^- ...
最新文章
- 在Ubuntu 16.04.3 LTS上玩转quic-go项目
- compareto方法_compare方法和compareTo方法区别
- docker 容器 defunct 僵尸进程
- IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小
- NYOJ 158 省赛来了
- 文件上传服务器经常超时,解决Tomcat文件上传超时问题.
- 2011.11.2 try
- CAD制图系列之中心线画法
- php 查询access数据库操作,php操作access数据库的方法详解
- 苹果在中国的审核规律探索一
- 网管员的任务与职责漫谈
- Smart210使用superboot刷机
- pc机箱 图纸_如何升级到新的PC机箱
- perfmon 端口修改_Jmeter插件之PerfMon监控插件使用说明
- Linux进程间通信(二)之信号量
- gitee代码管理仓库管理代码,更简单地查看各阶段的代码变动
- 调用百度地图Api,定位到大西洋的问题
- SDIO wifi Marvell8801/Marvell88w8801 介绍(七) ---- Marvell8801/Marvell88w8801实现搜索功能
- visualGDB下导入cmake工程
- 公务员笔试讲义——资料分析1
热门文章
- matlab极坐标六边形图片,matlab怎样直接画出六边形
- 三次样条曲线插值的基本原理及其C#实现
- 【Ruby on Rails全栈课程】3.5 注册功能
- 微软的服务器流量计费,微软修改Windows 10更新策略 即使按流量计费也自动更新...
- 扩展卡尔曼滤波(EKF)算法详细推导及仿真(Matlab)
- Apply pay详解
- 国美金融贷款模块解析HTML,国美金融贷款支持网站链接
- Fortinet 修复6个高危漏洞
- 阿里达摩院python教程真的吗_阿里达摩院出品的459集的python教程,据说懂中文就能入门高清版...
- Apkbus不错的源码汇总