辽宁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中的数 ...
随机推荐
- .NET并行与多线程学习系列一
并行与多线程学习系列一 一.并行初试: public static void test() { ; i < ; i++) { Console.WriteLine(i); } } public s ...
- CSS控制文本在一行内显示,若有多余字符则使用省略号表示
强制文本在一行内显示,多余字符使用省略号 text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
- (三)Harbor使用OpenLDAP认证登陆
接上一篇<安装Harbor>,安装好之后,接下来我们使用OpenLDAP来进行Harbor web界面的登陆验证及权限分配! OpenLDAP: 使用OpenLDAP的都知道,这是一个集 ...
- 清楚float浮动的四种方法
1.对父级设置适合CSS高度 对父级设置适合高度样式清除浮动,这里对“.divcss5”设置一定高度即可,一般设置高度需要能确定内容高度才能设置. 2.clear:both清除浮动 为了统一样式,我们 ...
- iOS 加载Image的两种方式
Apple官方文档对于加载image提供了两个方法 + (nullable UIImage *)imageNamed:(NSString *)name; + (nullable UIImage *)i ...
- 遍历HashMap的最佳方式
public static void printMap(Map mp) { Iterator it = mp.entrySet().iterator(); while (it.hasNext()) { ...
- HTML学习总结(四)【canvas绘图、WebGL、SVG】
一.Canvas canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术.<canvas> 标记和 ...
- HTML5学习总结——HTML5入门与新增标签
一.HTML5概要 1.1.为什么需要HTML5 概念: HTML5 是继 HTML4.01, XHTML 1.0 和 DOM 2 HTML 后的又一个重要版本, 旨在消除富 Internet 程序( ...
- 利用python3.5 构建流媒体后台音视频切换的服务端程序
#!/usr/bin/env python3.5.0 # -*- coding:utf8 -*- import os,sys,socket,hashlib,time,select,threading, ...
- Mediawiki随笔
http://www.ibm.com/developerworks/cn/opensource/os-mediawiki/ 定制wiki http://www.zzbaike.com/wiki/Me ...