UTPC2013 C 直径
問題
日本語なので本文参照(http://utpc2013.contest.atcoder.jp/tasks/utpc2013_03)
二つの重みなし無向グラフが与えられるので、
それを一本の辺でつなぐとき、
- できたグラフの直径を最小にするようにつないだときの直径
- できたグラフの直径を最大にするようにつないだときの直径
をそれぞれ出力せよ。
制約条件
それぞれの頂点数≦1000
それぞれの辺数≦10000
方針
重みなしグラフなので、グラフの直径は全ての頂点から毎回幅優先をする
O(n * m)で間に合う。
これで、最大の直径をもつところの始点同士をつなぐ、
最小の直径をもつところの始点同士をつなぐ、
とするのがベストなつなぎかた。
で、つないだ後でもう一回直径を求めればいい。
幅優先しなおして求めなくて計算で求められるのだけど、コーナーケースがあるので危険。
Aの直径 + Bの直径 + 1とかになるが、最小同士をつないだ値は、元の直径未満になってしまうことがあるので、その場合もとの直径の大きい方を答えなければならない。
ソースコード
bool v[1000]; pi diameter(){ int n, m; cin >> n >> m; vector<vi> e(n); rep(i, m){ int a, b; cin >> a >> b; e[a].pb(b); e[b].pb(a); } int mx = 0, mn = inf; rep(i, n){ memset(v, 0, sizeof(v)); queue<pi> q; q.push(mp(i, 0)); int dist = 0; while(!q.empty()){ int c = q.front().first, co = q.front().second; q.pop(); if(v[c]) continue; v[c] = 1; dist = max(dist, co); rep(j, e[c].size()){ int to = e[c][j]; if(!v[to]) q.push(mp(to, co + 1)); } } mx = max(mx, dist); mn = min(mn, dist); } return mp(mx, mn); } int main(){ pi a = diameter(); pi b = diameter(); //dbg(a); dbg(b); cout << max(max(a.first, b.first), a.second + b.second + 1) << " " << a.first + b.first + 1 << endl; return 0; }