CDOJ_1147 (最短路条数)

来源:互联网 发布:qq电话会议软件 编辑:程序博客网 时间:2024/05/11 04:55

秋实大哥带我飞

Time Limit: 300/100MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

Qiushidage Bring Me Fly

然而题目和题面并没有什么关系。

给出n个点,m条带权无向边,问你从1号点到n号点的最短路中有多少种走法?

Input

第一行两个数n,m分别表示点的个数和边的个数。(2n20001m2000

接下来m行,每行3个数u,v,w表示u号点到v号点有一条距离为w的边。(1u,vn0w100000

数据保证1号点能够到达n号点,点和边都可以被走多次。

Output

如果有无穷种走法,输出-1。否则输出走法的方案数mod 1000000009

Sample input and output

Sample InputSample Output
4 41 2 11 3 12 4 13 4 1
2
4 41 2 11 3 12 4 13 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 0typedef 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[n]){return true;}}return false;}void solve(){dijkstra(dist1, sum1, 1);dijkstra(dist2, sum2, n);if(check()) printf("-1\n");else printf("%lld\n", sum1[n] % mod);}int main(){input();solve();exit();}


0 0
原创粉丝点击