辽宁OI2016夏令营模拟T2-road
最短路(road.pas/c/cpp)
题目大意
有一个点数为 n,边数为 m 的无向图,点的编号为 1 到 n。边的权值均为非负数。
现在请你求出从点 1 到点 n 的最短路径条数,若有无限条则输出-1,答案对于
1000000009 取模。
输入文件
输入文件为 road.in。
输入共有 m+1 行。
第一行有两个整数 n,m,表示图中所有的点数与边数。
接下来的 m 行,每行三个整数 x,y,z,表示了一条边的起点、终点以及该边的长度。
输出文件
输出文件为 road.out。
输出一个整数表示从点 1 至点 n 的最短路径条数,答案对于 1000000009 取模。
样例输入
4 4
1 2 1
1 3 1
2 4 1
3 4 1
样例输出
2
数据规模与约定
对于 10%的数据,n≤10,m≤10;
对于 40%的数据,n≤1000,m≤2000;
对于 100%的数据,n≤100000,m≤200000;
保证到任意一点最短路的长度不超过 64 位有符号长整型范围。
————————————————题解
这道题的出题人数据范围根本没有超过int,orz
本来写了从前面一次spfa,从后一次spfa,枚举每个点,本来能很暴力地过几个水水的点,结果没打cstring,memset挂编了……本机不给memset提示真是的
然后更难过的是回家写程序整理题的时候出题人出数据卡spfaQAQ,卡到了9s!!!太难过了,从此得到了一个教训就是复杂度能满足O((n+m)logn)的都用dijkstra吧,虽然有点朴素但人家是稳定的好算法,还可以线段树或者小根堆的这么愉快的搞一搞。
好的这道题的思路是建一个最短路图再在上面dp,当时有点懵,因为不知道啥叫最短路图,dp也写的很烂……
那么就这样把思路梳理一下吧,会了就好……
首先我们需要跑一遍最短路,对于这道题来说必须用Dijskra(因为出题人卡spfa),随手敲一个priority_queue优化也能过,评测的电脑很快(但我的机器很慢orz)
然后我们考虑建图,如果一条边(u->v)是起点到v的最短路上的路径,那么dis[v]-dis[u]=val(u->v),不难理解
然后我们挑出所有这样的边,就是一张图,而且是DAG(有向无环图),按照拓扑序来dp就可以,dp到n就是我们想要的答案,画张图来说明

事实上我们只要按拓扑序给当前节点指向的节点加上方案数的大小就可以了
如果这张图上有一条边为0,我们可以绕着0边走无限次,此时方案数为-1
如果这张图某个能到达n的节点(有些节点可能到达不了n)插着一条边为0,我们也可以走无限次,此时方案数为-1
【答案为-1的一个数据】
4 4
1 2 1
1 3 1
2 4 1
3 4 0
把这些0边搞掉之后来谈这个拓扑序,也不用求一遍,就是起点1到哪个点距离来排(最小的一定是1),再使用一次dis数组即可,因为不存在0边与负边,最短路的值从小到大即为拓扑序顺序
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#define siji(i,x,y) for(int i=(x);i<=(y);i++)
#define gongzi(j,x,y) for(int j=(x);j>=(y);j--)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);i++)
#define sigongzi(j,x,y) for(int j=(x);j>(y);j--)
#define pil pair<int,long long>
#define pli pair<long long,int>//写了两个这个东西才觉得好蠢存边的时候值在前就可以很愉悦了……
#define fi first
#define se second
#define mo 1000000009
#define lnf 9223372036854775807LL
//#define inf 0x7fffffff
using namespace std;
typedef long long ll;
int n,m;
vector<pil> g[];
ll dis[];
int ans[];
int r[];
void init() {
scanf("%d%d",&n,&m);
int x,y;
ll z;
siji(i,,m) {
scanf("%d%d%lld",&x,&y,&z);
g[x].push_back(pil(y,z));
g[y].push_back(pil(x,z));
if(z==) ans[x]=ans[y]=-;
}
siji(i,,n) {dis[i]=lnf;}
}
priority_queue<pli> q;
void dijskra(int u){ dis[u]=;
q.push(pli(,));
while(!q.empty()) {
pli tmp =q.top();
q.pop();
if(-tmp.fi > dis[tmp.se]) continue;
int v=tmp.se;
int s=g[v].size()-; siji(j,,s) {
if(dis[v]+g[v][j].se<dis[g[v][j].fi]) {
dis[g[v][j].fi]=dis[v]+g[v][j].se;
q.push(pli(-dis[g[v][j].fi],g[v][j].fi));
//priority_queue默认大根堆,我们取反存就可以了,当你忘记了小值优先的算子的时候……
}
}
} }
bool cmp(int a,int b) {
return dis[a]<dis[b];
} inline void inc(int &a,int &b){a=a+b;while(a>=mo) a=a-mo;}//取模优化嘿嘿嘿
void graph() {
siji(i,,n) r[i]=i;
sort(r+,r+n+,cmp);//排序最短路来求拓扑序
if(ans[]==) ans[]=;
siji(i,,n) {
int t=g[r[i]].size()-;
siji(j,,t) {
if(dis[r[i]]+g[r[i]][j].se==dis[g[r[i]][j].fi]) {
if(ans[r[i]]==- || ans[g[r[i]][j].fi]==-) {
ans[g[r[i]][j].fi]=-;//在答案里标记一下插着0边的
}
else{
inc(ans[g[r[i]][j].fi],ans[r[i]]);
}
}
}
}
} void solve() {
dijskra();
graph();
printf("%d\n",ans[n]);//无限次的时候ans[n]就是-1了
}
int main(int argc, char const *argv[])
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
init();
solve();
return ;
}
辽宁OI2016夏令营模拟T2-road的更多相关文章
- 辽宁OI2016夏令营模拟T1-dis
数值距离(dis.pas/c/cpp)题目大意我们可以对一个数 x 进行两种操作:1. 选择一个质数 y,将 x 变为 x*y2. 选择一个 x 的质因数 y,将 x 变为 x/y定义两个数 a,b ...
- 辽宁OI2016夏令营模拟T3-chess
放棋子(chess.pas/c/cpp)题目大意现在有一个 n*m 的棋盘,现在你需要在棋盘上摆放 2n 个棋子,要求满足如下条件:1. 每一列只能有一个棋子:2. 每一行的前 xi 个格子有一个棋子 ...
- Day1:T1 模拟 T2 拓扑排序
T1:模拟 自己第一天的简直跟白痴一样啊...模拟都会打错.. 当时貌似在更新最大值的时候打逗比了... if((sum[x]==max && x<maxh) || sum[x] ...
- 洛谷金秋夏令营模拟赛 第2场 T11737 时之终末
这道题就是道状压dp...比赛的时候太贪心 然后状压又不好 所以T2 T3一起挂了QAQ 吸取教训QAQ f[i][j][k]表示前i个数选了j个 最后a个的状态为k的答案 #include<c ...
- 洛谷金秋夏令营模拟赛 第2场 T11738 伪神
调了一个下午只有八十分QAQ md弃了不管了 对拍也没拍出来 鬼知道是什么数据把我卡了QAQ 没事我只是个SB而已 这题其实还是蛮正常的 做法其实很简单 根据链剖的构造方法 你每次修改都是一段又一段的 ...
- 7.12模拟T2(套路容斥+多项式求逆)
Description: \(n<=10,max(w)<=1e6\) 题解: 考虑暴力,相当于走多维格子图,不能走有些点. 套路就是设\(f[i]\)表示第一次走到i的方案数 \(f[i] ...
- 「题解」:07.16NOIP模拟T2:通讯
问题 B: 通讯 时间限制: 1 Sec 内存限制: 256 MB 题面 题目描述 “这一切都是命运石之门的选择.” 试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短 信,并由此 ...
- 9.16noip模拟试题
题目描述 在幻想乡,东风谷早苗是以高达控闻名的高中生宅巫女.某一天,早苗终于入手了最新款的钢达姆模型.作为最新的钢达姆,当然有了与以往不同的功能了,那就是它能够自动行走,厉害吧(好吧,我自重).早苗的 ...
- PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记
PJ考试可能会用到的数学思维题选讲 by Pleiades_Antares 是学弟学妹的讲义--然后一部分题目是我弄的一部分来源于洛谷用户@ 普及组的一些数学思维题,所以可能有点菜咯别怪我 OI中的数 ...
随机推荐
- Java DB loadBalance 设计
Java DB loadBalance 设计 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {backgr ...
- 怎样通过WireShark抓到的包分析出SIP流程图
WireShark抓到了SIP包, 逐条分析, 看瞎...希望能够写个脚本, 自动生成流程图
- 网页视频下载牛逼工具,支持各种格式转换,比如腾讯视频格式qlv转mp4
这种思路真是创新,原文地址:http://jingyan.baidu.com/article/5225f26b03f047e6fb090860.html 软件工具名字:维棠下载. 上图: 1:搜索视频 ...
- neovim的新体验
A. 缘由 vim下的CtrlP插件好用,但是当文件较多时,不能很快检索,时有卡死的情况发生.听说neovim引入了很多新的功能,例如异步处理,job管理等. B. 安装neovim1. Ubunt ...
- DOM学习笔记--入门1
HTML DOM 是关于如何获取.修改.添加或删除 HTML 元素的标准. 首先节点有很多种,不仅仅HTML元素是节点,尤其 要注意文本节点的存在. 根据 W3C 的 HTML DOM 标准,HTML ...
- Python 自动给数字前面补0
为了排版方便或者是输出文件命名整洁,通常需要给数字前面补0来做统一.Python中有一个zfill函数用来给字符串前面补0,非常有用,这个zfill看起来也就是zero fill的缩写吧,看一下如何使 ...
- 在Freeplane中显示与隐藏层级图标
如下图所示,当选择了Edit → Icons → Show icons hierarchically时,给子节点Subsection 1.2.1添加的图标也同样会显示在其所有的父节点上,并且,它们并不 ...
- Shell终端收听音乐--豆瓣FM命令行版
douban.fm Terminal-based douban.fm inspired by douban.fm.该版本版基于Python2.* 安装Python2.* pacman -S pytho ...
- PHP检测文件能否下载
用php代码检测一个文件是否可以下载,网上没有找到合适的代码,自己实现了一个还挺好用的,分享给有需要的朋友. 基本原理:使用http的HEAD方法,检测报文的头里httpcode是否为200. pub ...
- HTML5学习之Web存储
在客户端存储数据 HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 之前, ...