模板题目:http://acm.uestc.edu.cn/#/problem/show/1147
此题数据较大所以用的long long
核心思想是:
- 设N为可以到v点的点集,vis[x]为s到x的最短路数,d[x]是s到x的最短距离,则vis[v]等于所有满足d[n] + dis[n][v] = d[v]的点n的vis[n]相加
- 在更新最短距离时,由于这个点不一定是第一次更新,所以直接赋值(对应注释1)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#define maxn 2005
using namespace std;
typedef long long ll;
typedef pair<int, int> P;//pair的好处是不用重载小于,可以直接比大小
const ll inf = 10000000000000;
int n, m;
ll vis[maxn];
ll d[maxn];
ll d1[maxn];
struct edge
{
int to;
int cost;
};
vector<edge> M[maxn];
void dijkstra(int s = 1)
{
for(int i = 1; i <= n; i++)
{
d[i] = inf;
vis[i] = 0;
}
d[s] = 0;
vis[s] = 1;
priority_queue<P, vector<P>, greater<P>> PQ;
PQ.push(make_pair(0, s));
while(!PQ.empty())
{
P cur = PQ.top();
PQ.pop();
int v = cur.second;
if(cur.first > d[v])
continue;
for(int i = 0; i < M[v].size(); i++)
{
edge e = M[v][i];
int u = e.to;
int cost = e.cost;
if(d[u] > d[v] + cost)
{
vis[u] = vis[v];//-----1
d[u] = d[v] + cost;
PQ.push(make_pair(d[u], u));
}
else if(d[u] == d[v] + cost)
{
vis[u] = vis[u] + vis[v];
vis[u] %= 1000000009;
}
}
}
//cout << vis[n] << endl;
}
int main()
{
cin >> n >> m;
for(int i = 0; i < maxn; i++)
M[i].clear();
for(int i = 0; i < 2 * m; i += 2)
{
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
edge tmp;
tmp.to = v;
tmp.cost = c;
M[u].push_back(tmp);
tmp.to = u;
tmp.cost = c;
M[v].push_back(tmp);
}
dijkstra();
swap(d, d1);
dijkstra(n);
bool flag = 1;
for(int i = 1; i <= n; i++)
{
int len = M[i].size();
for(int j = 0; j < len; j++)
{
if(M[i][j].cost == 0 && d1[i] + d[M[i][j].to] == d[1])
{
flag = 0;
}
}
}
if(flag)
{
cout << vis[1] << endl;
}
else
{
cout << -1 << endl;
}
return 0;
}