完全グラフはどのように向きづけしてもハミルトンパスが存在するというね!!!
その証明はすごく楽しいと思う!!!
問題概要
頂点数 の完全無向グラフが与えられる。今、すべての辺に向きをつけたい。各 i, j に対して
- 頂点 i から頂点 j へと向きをつけるコスト Cij
- 頂点 j から頂点 i へと向きをつけるコスト Cji
が与えられている。ただし作られる有向グラフにハミルトンパスが存在するようにしたい。そのようなことが可能となる向きづけの最小コストを求めよ。
制約
考えたこと
実は完全グラフであれば、どのように辺に向きをつけてもハミルトンパスが存在するのだ!!!!!!!!!!
ちなみに向き付きされた完全グラフのことをトーナメントグラフと呼ぶ。
簡単な数学的帰納法で示してみる。結構楽しい証明!!!!!
グラフ楽しい!!!
証明
頂点のトーナメントグラフの中から、頂点 を選び、残りの 頂点について帰納法の仮定からハミルトンパスが存在するので
とする。
Case 1
もし と を結ぶ辺が、 から へ向かう方向に向きづけられているならば、既に がハミルトンパスである。
Case 2
もし と を結ぶ辺が、 から へ向かう方向に向きづけられていたならば、既に がハミルトンパスである。
Case 3
以上のいずれも満たさないとき
- と の関係は 側から
- と の関係は 側から
という状況になっているが、ということは二分探索的な発想をすることで、ある添字 が存在して
- から への向きに辺がある
- から への向きに辺がある
という風になっているはずである。ちょうど中間値の定理と同じ考え方!!!!!!!
よって がハミルトンパスになっている。
詰め
本番であれば、以上のような証明は勘で済ませていい気がする。以上のことがわかっていれば
- 各辺 に対して独立に、 と のうちの小さい方
を Greedy にとっていけば良い。
#include <iostream> #include <vector> using namespace std; int main() { int N; cin >> N; vector<vector<long long> > C(N, vector<long long>(N)); for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> C[i][j]; long long res = 0; for (int i = 0; i < N; ++i) { for (int j = i+1; j < N; ++j) { res += min(C[i][j], C[j][i]); } } cout << res << endl; }