UVa 10917. Walk Through the Forest
Description
Jimmy的辦公室在森林的一邊,而他的家在森林的另一邊。
Jimmy想要每天都走不同的路徑回家。但是他也不想要回家太晚,所以他總是選擇一條可以朝他家「前進」的路徑來走。所謂「前進」指的是他會選擇從A點走到B點如果B點存在一條到他家的路徑長度比A點到他家任一路徑的長度都來的短的話。請你算出Jimmy共有多少種不同的路徑可以走。
Input Format
輸入包含多筆測資
第一列包含兩個整數N$(1 < N \le 1000)$和M,N代表有多少點(編號從1到N,請注意:編號1的點為Jimmy的辦公室,編號2的點為Jimmy的家),M代表共有多少個連接2個點的邊。接下來的M列每列有3個整數 a, b, d。a,b為點的編號,d 為連接 a,b 的路徑長(在這裡 a,b 不會相同,$1 \le d \le 1000000$)。路徑是雙向的,且任2點之間僅有一條路徑連接。
Output Format
每組測試資料輸出一列,Jimmy共有多少種不同的路徑可以走。
Sample Input
5 6
1 3 2
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24
7 8
1 3 1
1 4 1
3 7 1
7 4 1
7 5 1
6 7 1
5 2 1
6 2 1
5 7
Sample Output
2
4
Solution
這題還滿有趣的,因為朝家「前進」,所以需要重新構圖。
由於每步都會朝他家「前進」,所以可以先想到對於點2去做單源最短路徑(Dijkstra)。
然後再重新構圖,且這邊要注意是有向邊。
注意:以下Code點的編號是從0到N-1
Code
/*************************************************************************
> File Name: 10917 - A Walk Through the Forest.cpp
> Author: Samuel
> Mail: enminghuang21119@gmail.com
> Created Time: Tue Sep 4 12:04:50 2018
*************************************************************************/
#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> link[1001];
vector<int> rebuild[1001];
const int inf = 1 << 30;
int distant[1001];
int dp[1001];
bool visit[1001];
int n, m;
struct node {
int dis, index;
bool operator< (const node &b) const {
return dis > b.dis;
}
node() {}
node(int d, int i) : dis(d), index(i) {}
};
int dfs(int now) {
if (now == 1)
return 1;
if (dp[now] == -1) {
dp[now] = 0;
for (auto i : rebuild[now])
dp[now] += dfs(i);
}
return dp[now];
}
void dijkstra() {
priority_queue<node> pq;
pq.push(node(0, 1));
int cur;
distant[1] = 0;
while (!pq.empty()) {
cur = pq.top().index;
pq.pop();
if (visit[cur])
continue;
visit[cur] = 1;
for (auto i : link[cur]) {
int next = i.first;
int dis = i.second;
if (distant[next] > distant[cur] + dis) {
distant[next] = distant[cur] + dis;
pq.push(node(distant[next], next));
}
}
}
}
void build() {
memset(dp, -1, sizeof(dp));
int next, dis;
for (int i = 0; i < n; i++) {
rebuild[i].clear();
for (auto j : link[i])
if (distant[i] > distant[j.first])
rebuild[i].emplace_back(j.first);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int a, b, c;
while (cin >> n >> m && n) {
memset(link, 0, sizeof(link));
memset(visit, 0, sizeof(visit));
for (int i = 0;i < n; i++)
distant[i] = inf;
while (m--) {
cin >> a >> b >> c;
link[--a].push_back({--b, c});
link[b].push_back({a, c});
}
dijkstra();
build();
cout << dfs(0) << '\n';
}
}