題目: UVa - 12319 - Edgetown’s Traffic Jams

題目說明

給一個無向圖及一個有向圖,兩圖上的點數量一樣,求任兩點的最短路徑在有向圖上是否大於在無向圖上的 A 倍加 B

Input: 每組測資第一個整數 N 表示有 N 個點 **( 編號為 1 ~ N )**,後面 N 行依序為無向圖的連接情況,再後面 N 行依序為有向圖的連接情況,每行至少有一個整數 u,後面的數字表示有 u 到該數字的邊,且邊的路徑長為 1。

Output: 若任兩點的最短路徑在有向圖上大於在無向圖上的 A 倍加 B 輸出 “Yes”,否則輸出 “No”。

解題思路

這個解法需要有 Floyd-Warshall 演算法的概念。

先讀取測資,若任兩點沒有邊連接,則路徑長初始化為無限大( 1e9 ),之後使用 Floyd-Warshall 演算法找出圖上任兩點的最短路徑,再依照題目要求判斷即可。

參考解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <bits/stdc++.h>

using namespace std;

/*
reference:
https://ppt.cc/fJv50x
Floyd-Warshall Algorithm:
https://ppt.cc/fstMux
https://ppt.cc/fsQm1x
*/

static auto __ = []
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
return 0;
}();

const int inf = (int)1e9;

int N;
int a, b;
int G1[101][101];
int G2[101][101];

void init()
{
fill(G1[0], G1[0] + 101 * 101, inf);
fill(G2[0], G2[0] + 101 * 101, inf);
}

void readGraph(int (*G)[101])
{
int tmp;
string str;
stringstream ss;
for (int i = 1; i <= N; ++i)
{
getline(cin, str);
ss.clear();
ss.str(str);
ss >> tmp;
while (ss >> tmp) G[i][tmp] = 1;
}
}

void FloydWarshall()
{
for (int k = 1; k <= N; ++k)
{
for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j)
{
G1[i][j] = min(G1[i][j], G1[i][k] + G1[k][j]);
G2[i][j] = min(G2[i][j], G2[i][k] + G2[k][j]);
}
}
}

bool solve()
{
for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j)
if (i != j && G2[i][j] > G1[i][j] * a + b) return false;
return true;
}

int main()
{
while ((cin >> N).ignore() && N)
{
init();

readGraph(G1);
readGraph(G2);
cin >> a >> b;

FloydWarshall();

if (solve()) cout << "Yes\n";
else cout << "No\n";
}
}

參考資料

Uva 12319 Edgetown’s Traffic Jams @ louisfghbvc的部落格 :: 痞客邦 ::
[演算法] 最短路徑 (Floyd-Warshall 演算法) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
All-Pairs Shortest Path:Floyd-Warshall Algorithm