$\newcommand{\O}{\mathrm{O}}$ My Algorithm : kopricky アルゴリズムライブラリ

kopricky アルゴリズムライブラリ

Namori

コードについての説明

なもりグラフとは $n$ 頂点 $n$ 辺の連結な無向グラフのことでグラフはサイクル+サイクルから生える木の構造になる. 名称の由来は このアカウント のアイコンだそうです.
以下の実装はサイクル上の頂点を loop に, サイクルから生える木を graph に格納する(分解する)ような実装になっている.

時間計算量: $\O (n)$

コード

class Namori{
public:
    int V;
    vector<vector<int> > G, graph;
    vector<int> deg, loop;
    vector<bool> flag;
    Namori(int node_size) : V(node_size), G(V), deg(V, 0), flag(V, false){}
    void add_edge(int u,int v){
        G[u].push_back(v), G[v].push_back(u);
        deg[u]++, deg[v]++;
    }
    void dfs(int u){
        loop.push_back(u);
        for(int v : G[u]){
            if(flag[v]) continue;
            flag[v] = true;
            dfs(v);
        }
    }
    void build(){
        graph.resize(V);
        queue<int> que;
        // 葉の頂点を que に突っ込む
        for(int i = 0; i < V; i++){
            if(deg[i] == 1){
                que.push(i);
                flag[i] = true;
            }
        }
        // 葉からサイクル上の頂点に向かって登っていく
        while(!que.empty()){
            int p = que.front();
            que.pop();
            for(int v : G[p]){
                if(flag[v]) continue;
                deg[v]--;
                //サイクルから端
                graph[v].push_back(p);
                //端からサイクル
                graph[p].push_back(v);
                if(deg[v] > 1) continue;
                que.push(v);
                flag[v] = true;
            }
        }
        // サイクル上の頂点を loop に格納
        for(int i = 0; i < V; i++){
            if(flag[i]) continue;
            flag[i] = true;
            dfs(i);
            break;
        }
    }
};

verify 用の問題

Atcoder : Namori Grundy 提出コード