# 題目: UVa 10171 - Meeting Prof. Miguel

# 題目說明

給一個有 weight 的有向圖,圖中的道路有年齡限制
YM 的起始點,求 YM 要會合的最短路徑


INPUT:
每筆測資第一行輸入一個整數 N ,代表接下來有 N

接著輸入四個大寫字元 ageconnectuv ,與一個整數 w

  1. age = Y 代表只有年輕人能走的路、 age = M 代表只有老人能走的路
  2. connect = U 為單向連通、 connect = B 為雙向連通
  3. u 連接到 vweight(cost)w

接下來有兩個大寫字元 ym ,前者代表年輕人的起始點,後者代表老人的起始點

N0 時結束程式


OUTPUT:
輸出 YM 會合的最短路徑與會合的點
如果無法會合,則輸出 You will never meet.

# 解題方法

定義兩個 vector< vector<int> > ,分別為 G[0]G[1]
G[x][i][j] 代表從 ij 的最短路徑
先將 G[x] 中所有元素設為 501 ,相當於無限大 (題目限制範圍為 < 500 )

判斷 age 為年輕人 (tmp = 0) 或老人 (tmp = 1)
G[tmp][U][V] 設為 w ,若為雙向則將 G[tmp][V][U] 設為 w

記得將自己走到自己設為 0
對於所有 0 ~ 25iG[tmp][i][i] = 0

接下來跑 Floyd-Warshall algorithm (佛洛依德演算法)
轉移方程為: G[tmp][i][j] = min(G[tmp][i][j], G[tmp][i][k] + G[tmp][k][j])

最後判斷是否會合,與輸出匯合點

# 參考程式碼

#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main() 
{
	// fast io
	ios::sync_with_stdio(false);
	cout.tie(nullptr);
	cin.tie(nullptr);
	int N, w, U, V, Y, M, tmp;
	char age, connect, u, v, y, m;
	vector< vector<int> > G[2];
	while (cin >> N, N)
	{
		// init
		G[0].assign(26, vector<int>());
		G[1].assign(26, vector<int>());
		for (int i = 0; i < 26; ++i) G[0][i].assign(26, 501), G[1][i].assign(26, 501);
		int Max = 0;
		int ans = 501;
		// store data in target graph
		for (int i = 0; i < N; ++i)
		{
			cin >> age >> connect >> u >> v >> w;
			U = u - 'A';
			V = v - 'A';
			if (age == 'Y') tmp = 0;
			else tmp = 1;
			G[tmp][U][V] = w;
			if (connect == 'B') G[tmp][V][U] = w;
			
			Max = max(Max, max(U, V));
		}
		for (int i = 0; i < 26; ++i) G[0][i][i] = G[1][i][i] = 0;
		// Floyd-Warshall algorithm
		for (int k = 0; k <= Max; ++k) for (int i = 0; i <= Max; ++i) for (int j = 0; j <= Max; ++j)
		{
			G[0][i][j] = min(G[0][i][j], G[0][i][k] + G[0][k][j]);
			G[1][i][j] = min(G[1][i][j], G[1][i][k] + G[1][k][j]);
		}
		cin >> y >> m;
		Y = y - 'A';
		M = m - 'A';
		for (int i = 0; i <= Max; ++i) ans = min(ans, G[0][Y][i] + G[1][M][i]);
		
		if (ans == 501) cout << "You will never meet.\n";
		else
		{
			cout << ans;
			for (int i = 0; i <= Max; ++i) if (ans == G[0][Y][i] + G[1][M][i]) cout << " " << char(i + 'A');
			cout << "\n";
		}
	}
	return 0;
}

# 參考資料

https://github.com/morris821028/UVa/blob/master/volume101/10171%20-%20Meeting%20Prof.%20Miguel.cpp