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

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

Chromatic Number Algorithm

コードについての説明(個人的メモ)

グラフの頂点を隣り合う頂点は違う色となるように彩色するのに必要な色の数の最小値を彩色数と言い, それを求めるアルゴリズムである.
また彩色数は補グラフでの最小クリーク被覆の値と等しいことが知られている.
このスライドがとても参考になる.

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

コード

// 頂点数は 32 以下であることを仮定
class ChromaticrNumber {
public:
    int V;
    vector<unsigned int> adj;
    const static unsigned int MOD = 1000000007;
    ChromaticrNumber(int node_size) : V(node_size), adj(V, 0){
        for(int i = 0; i < V; ++i){
            adj[i] = (1 << i);
        }
    }
    void add_edge(int u, int v){
        adj[u] |= (1 << v), adj[v] |= (1 << u);
    }
    int solve(){
        vector<unsigned int> t(1 << V, 0), I(1 << V, 0);
        t[(1 << V) - 1] = I[0] = 1;
        for(int i = 1; i < (1 << V); ++i){
            const int v = __builtin_ctz(i);
            I[i] = I[i ^ (1 << v)] + I[i & (~adj[v])];
            I[i] = (I[i] >= MOD) ? (I[i] - MOD) : I[i];
            t[i-1] = (((V - __builtin_popcount(i - 1)) % 2) ? (MOD - 1) : 1);
        }
        for(int k = 1; k < V; ++k){
            unsigned long long res = 0;
            for(int i = 0; i < (1 << V); ++i){
                res += (t[i] = (unsigned long long)t[i] * I[i] % MOD);
            }
            if(res % MOD) return k;
        }
        return V;
    }
};

verify 用の問題

Atcooder : Close Group 提出コード