题目:http://community.topcoder.com/stat?c=problem_statement&pm=13197&rd=15857
跟一般的最短路径问题不一样,本题要求所有的最短路径数,而且有0权值边,算法与Dijkstra算法有点类似,不同的的当找到一个点到源点最短路径长度时,并不标记该点为已访问点,而是加上该路径上前一个点的最短路径数, 并且标记已访问过的边,确保每条边只访问一次。关于0边的处理也要注意,基本思想就是任何一个点若与0边相连,则该点到源点的最短路径数必为无穷大,若一条最短路径上前一个点是这样的点,则后一个点也是这样的点。
代码:
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
/*************** Program Begin **********************/
const int MOD = 1000000009;
const int INF = 1000000000;
int ways[2001], dist[2001];
bool visited[2001]; // 防止重复访问0边
typedef pair<int, int> Node;
class DrivingPlans {
public:
int count(int N, vector <int> A, vector <int> B, vector <int> C) {
int res = 0;
int E = A.size();
memset(ways, 0, sizeof(ways));
ways[1] = 1;
for (int i = 1; i <= N; i++) {
dist[i] = INF;
}
dist[1] = 0;
memset(visited, 0, sizeof(visited));
set <Node> S;
for (int i = 0; i < E; i++) {
int u = A[i], v = B[i], w = C[i];
if (0 == w) {
ways[u] = ways[v] = -1;
}
if (1 == v) {
swap(A[i], B[i]);
swap(u, v);
}
if (1 == u) {
dist[v] = w;
visited[i] = true;
S.insert(mkp(w, i));
}
}
while (!S.empty()) {
int shortest = (*S.begin()).first;
int k = (*S.begin()).second;
S.erase(S.begin());
int cur = B[k];
if (shortest == dist[cur]) { // 若该条路径为最短路径,则更新ways[]
// update ways
if (C[k] != 0 && ways[A[k]] != -1 && ways[cur] != -1) {
ways[cur] += ways[A[k]];
ways[cur] %= MOD;
} else {
ways[cur] = -1;
}
} else {
continue;
}
// update
for (int i = 0; i < E; i++) {
if (visited[i]) {
continue;
}
int u = A[i], v = B[i], w = C[i];
if (v == cur) {
swap(A[i], B[i]);
swap(u, v);
}
if (u == cur && shortest + w <= dist[v]) {
set <Node>::iterator it = S.find(mkp(dist[v], i));
if (it != S.end()) {
S.erase(it);
}
dist[v] = shortest + w;
S.insert(mkp(dist[v], i));
visited[i] = true;
}
}
}
res = ways[N];
return res;
}
};
/************** Program End ************************/