題目: UVa - 10171 - Meeting Prof. Miguel…

題目說明

給兩個圖 MY,圖上的點相同,但相通的邊不同,每條邊都有各自的 cost,兩個人各自在圖上走,各自給一個起點,求兩者可相遇且兩人的 cost 總和最小的 cost 及相遇的點,若最小 cost 的點有多個需要全部輸出。

Input: 每組測資第一個數字 m,表示有 m 行資料,每行資料為四個字符及一個數字組成,依序為 abuvwa 表示該行測資是哪個圖上的,b 表示該邊為單向或雙向 ( B 為雙向 ),u、v、w 依序為邊上兩點及 cost。

Output: 輸出兩者可相遇且兩人的 cost 總和最小的 cost 及相遇的點,若最小 cost 的點有多個需要全部輸出。

解題思路

All Pair Shortest Path 題,讀測資並做 Floyd-Warshall Algorithm 求解即可。需要注意的是測資給的邊可能有重複,此時取 cost 較小者。

參考解法

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
#include <bits/stdc++.h>

using namespace std;

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

const int INF = (int)1e9;

int m;
int G1[26][26];
int G2[26][26];

void init()
{
for (int i = 0; i < 26; ++i)
{
for (int j = 0; j < 26; ++j) G1[i][j] = G2[i][j] = INF;
G1[i][i] = G2[i][i] = 0;
}
}

void read()
{
int w;
char a, b, u, v;
while (m--)
{
cin >> a >> b >> u >> v >> w;
auto ptr = (a == 'Y') ? G1 : G2;

u -= 'A', v -= 'A';
ptr[u][v] = min(w, ptr[u][v]);
if (b == 'B') ptr[v][u] = min(w, ptr[v][u]);
}
}

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

void solve()
{
char a, b;
cin >> a >> b;
a -= 'A', b -= 'A';

int mn = INF;
for (int k = 0; k < 26; ++k) mn = min(G1[a][k] + G2[b][k], mn);

if (mn == INF) { cout << "You will never meet.\n"; return; }

cout << mn;
for (int k = 0; k < 26; ++k) if (G1[a][k] + G2[b][k] == mn)
cout << ' ' << char(k + 'A');
cout << '\n';
}

int main()
{
while (cin >> m && m)
{
init();
read();
FloydWarshall();
solve();
}
}