最短路(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的更多相关文章

  1. 辽宁OI2016夏令营模拟T1-dis

    数值距离(dis.pas/c/cpp)题目大意我们可以对一个数 x 进行两种操作:1. 选择一个质数 y,将 x 变为 x*y2. 选择一个 x 的质因数 y,将 x 变为 x/y定义两个数 a,b ...

  2. 辽宁OI2016夏令营模拟T3-chess

    放棋子(chess.pas/c/cpp)题目大意现在有一个 n*m 的棋盘,现在你需要在棋盘上摆放 2n 个棋子,要求满足如下条件:1. 每一列只能有一个棋子:2. 每一行的前 xi 个格子有一个棋子 ...

  3. Day1:T1 模拟 T2 拓扑排序

    T1:模拟 自己第一天的简直跟白痴一样啊...模拟都会打错.. 当时貌似在更新最大值的时候打逗比了... if((sum[x]==max && x<maxh) || sum[x] ...

  4. 洛谷金秋夏令营模拟赛 第2场 T11737 时之终末

    这道题就是道状压dp...比赛的时候太贪心 然后状压又不好 所以T2 T3一起挂了QAQ 吸取教训QAQ f[i][j][k]表示前i个数选了j个 最后a个的状态为k的答案 #include<c ...

  5. 洛谷金秋夏令营模拟赛 第2场 T11738 伪神

    调了一个下午只有八十分QAQ md弃了不管了 对拍也没拍出来 鬼知道是什么数据把我卡了QAQ 没事我只是个SB而已 这题其实还是蛮正常的 做法其实很简单 根据链剖的构造方法 你每次修改都是一段又一段的 ...

  6. 7.12模拟T2(套路容斥+多项式求逆)

    Description: \(n<=10,max(w)<=1e6\) 题解: 考虑暴力,相当于走多维格子图,不能走有些点. 套路就是设\(f[i]\)表示第一次走到i的方案数 \(f[i] ...

  7. 「题解」:07.16NOIP模拟T2:通讯

    问题 B: 通讯 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 “这一切都是命运石之门的选择.” 试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短 信,并由此 ...

  8. 9.16noip模拟试题

    题目描述 在幻想乡,东风谷早苗是以高达控闻名的高中生宅巫女.某一天,早苗终于入手了最新款的钢达姆模型.作为最新的钢达姆,当然有了与以往不同的功能了,那就是它能够自动行走,厉害吧(好吧,我自重).早苗的 ...

  9. PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记

    PJ考试可能会用到的数学思维题选讲 by Pleiades_Antares 是学弟学妹的讲义--然后一部分题目是我弄的一部分来源于洛谷用户@ 普及组的一些数学思维题,所以可能有点菜咯别怪我 OI中的数 ...

随机推荐

  1. C语言之形参和实参

    一 形参与实参 1).定义 形参:形式参数. 就是定义函数的时候,写在函数名小括号后面的参数叫形参 实参:实际参数. 就是调用函数的时候,调用函数时写在函数名小括号后面的参数就叫实参 2).注意项 a ...

  2. css透明度(兼容所有浏览器)

    .transparent{ background: rgba(, , , 0.3) !important; /* IE无效,FF有效 */ filter: alpha(opacity=); -moz- ...

  3. OpenH264

    转自:http://blog.csdn.net/chinabinlang/article/details/41209053 目前最常用的264工程师x264: 最近有又有一个开源工程OpenH264, ...

  4. 在使用cognos时遇到的问题记录帖

    在使用cognos时遇到的问题记录帖 1.开一个project 报无法访问位于 URL 的服务: http://localhost:80/ibmcognos/cgi-bin/cognos.cgi?b_ ...

  5. 【NOIP2014】DAY2题解+代码

    T1 傻逼题……不想写贴昨年代码了. 总之随便怎么搞都能过. 15年的DAY2T1怎么那么毒瘤真是越活越倒退] #include <iostream> #include <fstre ...

  6. 新发现的一些C函数

    今天看lsocket代码,发现有三个C函数,以前一直没有用过. 觉得特别有意思,一个strspn,一个strrchr,一个getaddrinfo. strspn #include <string ...

  7. c#的as关键字

    类型a  as 类型b   ,把类型a强制变为类型b

  8. CodeForces 689D Friends and Subsequences

    枚举,二分,$RMQ$. 对于一个序列来说,如果固定区间左端点,随着右端点的增大,最大值肯定是非递减的,最小值肯定是非递增的. 因此,根据这种单调性,我们可以枚举区间左端点$L$,二分找到第一个位置$ ...

  9. mac下 redis安装使用

    安装redis:brew install redis 开启redis服务:redis-server /usr/local/etc/redis.conf 重新打开一个命令窗口:redis-cli ,进入 ...

  10. MySQL之索引优化

    很多数据库系统性能不理想是因为系统没有经过整体优化,存在大量性能低下的SQL 语句.这类SQL语句性能不好的首要原因是缺乏高效的索引.没有索引除了导致语句本身运行速度慢外,更是导致大量的磁盘读写操作, ...