# 題目: UVa 10449 - Traffic
# 題目說明
給一個有向圖,圖中每個點皆有值,而從一個點移動到下一個點的 cost 為 (目的點的值 - 當前點的值) * 3
求 1
到終點的最短路徑
INPUT:
每筆測資第一個輸入為整數 n
,代表有 n
個點
接下來有 n
個整數,代表從 1 ~ n
的點的值
第二行有一個整數 m
,代表有 m
條邊
接下來有 m
行,每行有兩個整數,代表前者連接到後者 (單向)
最後有一個整數 q
,代表終點的數量
之後 q
個整數代表終點的位置
OUTPUT:
輸出從 1
到終點的最短路徑
如果最短路徑或無法找到,則輸出 ?
# 解題方法
先儲存個點的值及建圖
接著以 bellman
演算法找到最短路徑,如果有負的值,則 push 至 unordered_set
內
# 參考程式碼
#include <iostream> | |
#include <memory.h> | |
#include <vector> | |
#include <math.h> | |
#include <climits> | |
#include <unordered_set> | |
using namespace std; | |
vector< vector< pair<int, int> > > edge; | |
int busyness[201]; | |
int dis[201]; | |
unordered_set<int> store; | |
void bellman(int n) | |
{ | |
dis[1] = 0; | |
for (int i = 0; i < n - 1; ++i) for (int u = 1; u <= n; ++u) | |
{ | |
for (auto& [v, w] : edge[u]) if (dis[u] != INT_MAX) dis[v] = min(dis[v], dis[u] + w); | |
} | |
for (int u = 1; u <= n; ++u) for (auto& [v, w] : edge[u]) | |
{ | |
if (dis[v] > dis[u] + w) | |
{ | |
dis[v] = dis[u] + w; | |
store.emplace(v); | |
} | |
} | |
} | |
int main() | |
{ | |
// fast io | |
ios::sync_with_stdio(false); | |
cin.tie(nullptr); | |
cout.tie(nullptr); | |
int n, cases = 0; | |
while (cin >> n) | |
{ | |
// init | |
edge.assign(n + 1, vector< pair<int, int> >()); | |
memset(busyness, 0, sizeof(busyness)); | |
fill(dis, dis + 201, INT_MAX); | |
store.clear(); | |
for (int i = 1, tmp; i <= n; ++i) cin >> tmp, busyness[i] = tmp; | |
int m, u, v; | |
cin >> m; | |
while (m--) cin >> u >> v, edge[u].push_back({ v, pow(busyness[v] - busyness[u], 3.0)}); | |
bellman(n); | |
cout << "Set #" << ++cases << "\n"; | |
int q, num; | |
cin >> q; | |
while (q--) | |
{ | |
cin >> num; | |
if (store.count(num) || dis[num] < 3 || dis[num] == INT_MAX) cout << "?\n"; | |
else cout << dis[num] << "\n"; | |
} | |
} | |
return 0; | |
} |
# 參考資料
https://www.larrysprognotes.com/UVa%20-%2010449/