# 題目: UVa 1112 - Mice and Maze
# 題目說明
有一張有向圖,每個點走到另一個點都會花費時間
每個點走到終點都有一條最短路徑
求有多少點能在時間限制內走到終點
INPUT:
第一行有一個整數 T
,代表有 T
筆測資
每筆測資第一行有四個整數 N
、 End
、 Time
、 M
N
代表有N
個點End
代表終點Time
代表時間限制M
代表有幾個邊
接下來有 M
行,每行有三個整數 u
、 v
、 w
代表 u
點及 v
點間有一條長 w
的邊
OUTPUT:
輸出能在時間限制內走到終點的點的數量
終點也算一個點
# 解題方法
如果從每個點開始走到終點,會很麻煩,所以改為從終點開始走 (存 edge
的時候反向存)
以 dijkstra
演算法搭配 priority_queue
建出終點到每一個點的最小路徑
最後再判斷每個點的最小路徑有沒有在時間限制內
# 參考程式碼
#include <iostream> | |
#include <queue> | |
#include <vector> | |
#include <memory.h> | |
using namespace std; | |
typedef pair<int, int> p; | |
vector< vector<p> > edge; | |
priority_queue<p, vector<p>, greater<p>> pq; | |
int vals[101]; | |
int vis[101]; | |
void dijkstra(int End) | |
{ | |
vals[End] = 0; | |
pq.push({ 0, End }); | |
while (!pq.empty()) | |
{ | |
auto [val, u] = pq.top(); | |
pq.pop(); | |
vis[u] = true; | |
for (auto& [v, w] : edge[u]) if (!vis[v]) | |
{ | |
int tmp = val + w; | |
if (vals[v] == -1 || vals[v] > tmp) | |
{ | |
vals[v] = tmp; | |
pq.push({ tmp, v }); | |
} | |
} | |
} | |
} | |
int main() | |
{ | |
// fast io | |
ios::sync_with_stdio(false); | |
cin.tie(nullptr); | |
cout.tie(nullptr); | |
int T; | |
cin >> T; | |
while (T--) | |
{ | |
int N, End, Time, M; | |
cin >> N >> End >> Time >> M; | |
// init | |
edge.assign(N + 1, vector<p>()); | |
memset(vis, false, sizeof(vis)); | |
for (int i = 0; i < 101; ++i) vals[i] = Time + 1; | |
while (M--) | |
{ | |
int u, v, w; | |
cin >> u >> v >> w; | |
edge[v].push_back({ u, w }); | |
} | |
// dijkstra algorithm | |
dijkstra(End); | |
int count = 0; | |
for (int i = 1; i <= N; ++i) if (vals[i] <= Time) ++count; | |
cout << count << "\n"; | |
if (T) cout << "\n"; | |
} | |
return 0; | |
} |
# 參考資料
https://www.larrysprognotes.com/UVa%20-%201112/