# 題目: UVa 821 - Page Hopping

# 題目說明

u與v最短路徑的加總,再除以u與v的組合數
(u與v屬於G中任意兩點)


INPUT:
每次輸入兩個整數uv,代表u連到v,直到uv0
uv的第一次輸入皆為0,結束程式


OUTPUT:
輸出u與v最短路徑的加總,再除以u與v的組合數

# 解題方法

定義一個vector<vector<int>> GG[i][j]代表從ij的最短路徑
先將G中所有元素設為101,相當於無限大 (題目限制範圍為1 ~ 100)
G[u][v]設為1,代表weight

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

最後將u與v最短路徑加總
並算出u與v的組合數 = 不重複元素的size * (不重複元素的size - 1)
相除後即可輸出

# 參考程式碼

#include <iostream>
#include <vector>
#include <unordered_set>
#include <iomanip>
#include <climits>

using namespace std;

int main()
{
	// fast io
	ios::sync_with_stdio(false);
	cout.tie(nullptr);
	cin.tie(nullptr);

	int u, v, cases = 0;
	vector<vector<int>> G(101);
	unordered_set<int> S;

	while (cin >> u >> v, u && v)
	{
		// init
		for (int i = 0; i < G.size(); ++i) G[i].assign(101, 101);
		S.clear();
		double ans = 0;
		int Max = 0;

		do
		{
			G[u][v] = 1;
			Max = max(Max, max(u, v));
			S.emplace(u);
			S.emplace(v);

		} while (cin >> u >> v, u && v);

		// Floyd-Warshall algorithm
		for (int k = 1; k <= Max; ++k) for (int i = 1; i <= Max; ++i) for (int j = 1; j <= Max; ++j)
			G[i][j] = min(G[i][j], G[i][k] + G[k][j]);

		int Size = S.size() * (S.size() - 1);
		for (auto i = S.begin(); i != S.end(); ++i) for (auto j = S.begin(); j != S.end(); ++j)
			if (*i != *j) ans += G[*i][*j];

		cout << "Case " << ++cases << ": average length between pages = " << setprecision(3) << fixed << ans / Size << " clicks\n";
	}

	return 0;
}

# 參考資料

https://www.pinghenotes.com/UVa-12319-Edgetown-s-Traffic-Jams/