AOJ 2850 Endless BFS

解法

01BFSで解いた。
まず、2部グラフだと永遠に終わらないことはわかる。
2部グラフじゃない場合、どこかのタイミングで隣接2頂点が同時に current に入り、そこからそれらの頂点は一生消えない。
そして、そこからどんどん頂点集合が広がっていくことがわかる。

どのタイミングで初めて隣接2頂点が current に入るかは普通に BFS をして、隣接頂点が同じ距離にあることが条件である。
そういう隣接2頂点を見つけたら次からは stable (消えない)状態にうつして、そっちはそっちでBFSをする。
ただし、stable のときの遷移は注意が必要である。例えば今 stable な状態で v にいたとして、隣接頂点 u に移ることを考える。stable な v に至るまでのコストを c1、u の頂点0からの距離を c2 とすると、c1, c2 のパリティが等しいときはコストを0にする(v に至ったタイミングで、u も stable とみなせるから)。
なので、01BFS をすればよいということになる。

stable であるかそうでないかで頂点の数を2倍持っておけばよく、計算量は O(n + m) である。

ソースコード

#include <bits/stdc++.h>
using namespace std;

constexpr int inf = 1e9;

int main() {
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    for(int i = 0; i < m; ++i) {
        int u, v; cin >> u >> v;
        g[u - 1].push_back(v - 1);
        g[v - 1].push_back(u - 1);
    }

    vector<vector<int>> d(n, vector<int>(2, inf));
    d[0][0] = 0;
    deque<tuple<int, int>> que;
    que.emplace_back(0, 0);
    while(!que.empty()) {
        int v, stable;
        tie(v, stable) = que.front(); que.pop_front();
        if(stable == 0) {
            for(auto to : g[v]) {
                if(d[to][0] == d[v][0]) {
                    d[v][1] = d[v][0];
                    que.emplace_back(v, 1);
                }
                if(d[to][0] == inf) {
                    d[to][0] = d[v][0] + 1;
                    que.emplace_back(to, 0);
                }
            }
        } else {
            for(auto to : g[v]) {
                if(d[to][1] != inf) continue;
                if((d[to][0] & 1) == (d[v][1] & 1)) {
                    d[to][1] = d[v][1];
                    que.emplace_front(to, 1);
                } else {
                    d[to][1] = d[v][1] + 1;
                    que.emplace_back(to, 1);
                }
            }
        }
    }

    int ans = 0;
    for(int i = 0; i < n; ++i) {
        ans = max(ans, d[i][1]);
    }

    cout << (ans == inf ? -1 : ans) << endl;
}

感想

想定解はもっと賢かった。
最初にグラフ作るタイミングですでに頂点を2倍にしておいて、偶数を表す頂点と奇数を表す頂点間に辺をはる感じだった。そうするとただのBFSやるだけになる。
まあ解けたので良し。