CDOJ_1147 (最短路条数)
2015-11-18 20:03
423 查看
秋实大哥带我飞
Time Limit: 300/100MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)然而题目和题面并没有什么关系。
给出n个点,m条带权无向边,问你从1号点到n号点的最短路中有多少种走法?
Input
第一行两个数n,m分别表示点的个数和边的个数。(2≤n≤2000,1≤m≤2000)接下来m行,每行3个数u,v,w表示u号点到v号点有一条距离为w的边。(1≤u,v≤n,0≤w≤100000)
数据保证1号点能够到达n号点,点和边都可以被走多次。
Output
如果有无穷种走法,输出-1。否则输出走法的方案数
mod 1000000009。
Sample input and output
Sample Input | Sample Output |
---|---|
4 4 1 2 1 1 3 1 2 4 1 3 4 1 | 2 |
4 4 1 2 1 1 3 1 2 4 1 3 4 0 | -1 |
Source
2015 UESTC Training for Graph Theory分析:最短路条数问题。求最短路的条数只需要在dijkstra上面加一个数组sumt[]记录就行,sumt[v] 表示从源点 s 出发到 v 的最短路条数,当 dist[v] > dist[u] + d[u][v] 时,更新sumt[v] 的值就是 sumt[u];当 dist[v] == dist[u] + d[u][v] 时,sumt[v] += sumt[u];判断是否存在无数条最短路,即看是否存在这样的一条边(u, v),边权为 0,并且其中一条最短路经过这条边,也就是 源点 s 到 u 的最短距离 +
v 到终点 t 的最短距离 == 最短路长度,因为边权为 0 的话就可以来回无限次地走。所以需要两次最短路分别计算出源点 s 到每个点的最短路、每个点到终点 t 的最短路,然后枚举每条边,即可判断是否存在无数条最短路。
题目链接:http://acm.uestc.edu.cn/#/problem/show/1147
代码清单:
/******************************************************************************* *** problem ID : UESTC_1147.cpp *** create time : Wed Nov 18 14:22:41 2015 *** author name : nndxy *** author blog : http://blog.csdn.net/jhgkjhg_ugtdk77 *** author motto: never loose enthusiasm for life, life is to keep on fighting! *******************************************************************************/ #include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <ctime> #include <vector> #include <cctype> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <bits/stdc++.h> using namespace std; #define exit() return 0 typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxn = 2000 + 5; const int maxm = 2000 + 5; const int INF = 0x7f7f7f7f; const ll mod = 1e9 + 9; struct P{ int to, dis; P() {} P(int _to, int _dis) : to(_to), dis(_dis) {} friend bool operator<(P a, P b) { return a.dis > b.dis; } }; struct Edge{ int u, v, dis, next; }; int n, m; int a, b, c, num; int head[maxn]; Edge edge[maxm * 2]; ll sum1[maxn], sum2[maxn]; int dist1[maxn], dist2[maxn]; void addEdge(int u, int v, int dis){ edge[num].u = u; edge[num].v = v; edge[num].dis = dis; edge[num].next = head[u]; head[u] = num++; } void input(){ scanf("%d%d", &n, &m); num = 0; memset(head, -1, sizeof(head)); for(int i = 0; i < m; i++){ scanf("%d%d%d", &a, &b, &c); addEdge(a, b, c); addEdge(b, a, c); } } void dijkstra(int dist[], ll sumt[], int s){ fill(dist + 1, dist + 1 + n, INF); fill(sumt + 1, sumt + 1 + n, 0); priority_queue <P> q; while(!q.empty()) q.pop(); dist[s] = 0; sumt[s] = 1; q.push(P(s, 0)); while(!q.empty()){ P p = q.top(); q.pop(); int u = p.to; if(p.dis > dist[u]) continue; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(dist[v] > dist[u] + edge[i].dis){ sumt[v] = sumt[u] % mod; dist[v] = dist[u] + edge[i].dis; q.push(P(v, dist[v])); } else if(dist[v] == dist[u] + edge[i].dis){ sumt[v] = (sumt[v] + sumt[u]) % mod; } } } } bool check(){ for(int i = 0; i < num; i++){ int u = edge[i].u; int v = edge[i].v; if(edge[i].dis == 0 && dist1[u] + dist2[v] == dist1 ){ return true; } } return false; } void solve(){ dijkstra(dist1, sum1, 1); dijkstra(dist2, sum2, n); if(check()) printf("-1\n"); else printf("%lld\n", sum1 % mod); } int main(){ input(); solve(); exit(); }
相关文章推荐
- Javascript SHA-1:Secure Hash Algorithm
- 基于Java实现的Dijkstra算法示例
- 简单的四则运算
- 数的奇偶性
- Dijkstra和floyd——求单源点最短路径
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- [转]可视化的数据结构和算法
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 统计文件中不小于某一长度的单词的个数(泛型算法实现)
- 杭电题目---一只小蜜蜂
- 初学图论-Dijkstra单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现
- HDOJ 1002 A + B Problem II (Big Numbers Addition)