cplib-cpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub hitonanode/cplib-cpp

:heavy_check_mark: graph/test/max_weight_independent_set.lc.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/maximum_independent_set"
#include "../max_weight_independent_set.hpp"
#include <iostream>
using namespace std;

int main() {
    cin.tie(nullptr), ios::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    max_weight_independent_set<int> solver(N);
    while (M--) {
        int u, v;
        cin >> u >> v;
        solver.add_edge(u, v);
    }

    cout << solver.solve() << '\n';
    for (int i = 0; i < N; ++i) {
        if ((solver.solution_set >> i) & 1) cout << i << ' ';
    }
    cout << '\n';
}
#line 1 "graph/test/max_weight_independent_set.lc.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/maximum_independent_set"
#line 2 "graph/max_weight_independent_set.hpp"
#include <algorithm>
#include <cassert>
#include <stack>
#include <vector>

// Maximum weight independent set
// Requirement: n <= 63
// Complexity: exponential, O(1.381^n n)
// Reference: https://www.slideshare.net/wata_orz/ss-12131479, p.34
// Verified: https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3519
template <class Weight> struct max_weight_independent_set {
    int V; // # of vertices
    std::vector<long long> conn;
    std::vector<Weight> ws;

    long long solution_set; // Solution set is saved here: use (1) / not use (0)
    Weight eval_solution;   // optimal value

private:
    long long state;
    Weight eval_state;
    long long avail;
    void mis_dfs() {
        std::stack<int, std::vector<int>> st;
        for (bool retry = true; retry;) { // Pruning
            retry = false;
            for (int i = 0; i < V; i++) {
                if (avail & (1LL << i)) {
                    int nb = __builtin_popcountll(avail & conn[i]);
                    if (nb == 0) {
                        st.emplace(i), avail -= 1LL << i, state |= 1LL << i;
                        eval_state += ws[i];
                        retry = true;
                    }
                    if (nb == 1) {
                        int j = __builtin_ctzll(avail & conn[i]);
                        if (ws[i] >= ws[j]) {
                            st.emplace(i), avail -= 1LL << i, state |= 1LL << i;
                            eval_state += ws[i];
                            retry = true;
                            st.emplace(j), avail &= ~(1LL << j);
                        }
                    }
                }
            }
        }

        if (eval_state > eval_solution) eval_solution = eval_state, solution_set = state;

        int d = -1, n = -1;
        for (int i = 0; i < V; i++) {
            if (avail & (1LL << i)) {
                int c = __builtin_popcountll(avail & conn[i]);
                if (c > d) d = c, n = i;
            }
        }

        if (d >= 0) {
            long long nxt = avail & conn[n];
            avail -= 1LL << n;
            mis_dfs();
            state |= 1LL << n;
            eval_state += ws[n];
            avail &= ~nxt;
            mis_dfs();
            avail |= nxt;
            avail |= 1LL << n;
            state &= ~(1LL << n);
            eval_state -= ws[n];
        }

        for (; st.size(); st.pop()) {
            int i = st.top();
            avail |= 1LL << i;
            if ((state >> i) & 1LL) state -= 1LL << i, eval_state -= ws[i];
        }
    }

public:
    max_weight_independent_set(const int V)
        : V(V), conn(V), ws(V, Weight(1)), solution_set(0), eval_solution(Weight()), state(0),
          eval_state(Weight()), avail((1LL << V) - 1) {}
    max_weight_independent_set(const std::vector<Weight> &ws_)
        : max_weight_independent_set(ws_.size()) {
        ws = ws_;
    }

    void add_edge(int u, int v) {
        assert(u != v);
        assert(0 <= u and u < V);
        assert(0 <= v and v < V);
        conn[u] |= 1LL << v;
        conn[v] |= 1LL << u;
    }

    Weight solve() {
        state = 0, eval_state = Weight(), avail = (1LL << V) - 1;
        solution_set = 0, eval_solution = Weight();
        mis_dfs();
        return eval_solution;
    }
};
#line 3 "graph/test/max_weight_independent_set.lc.test.cpp"
#include <iostream>
using namespace std;

int main() {
    cin.tie(nullptr), ios::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    max_weight_independent_set<int> solver(N);
    while (M--) {
        int u, v;
        cin >> u >> v;
        solver.add_edge(u, v);
    }

    cout << solver.solve() << '\n';
    for (int i = 0; i < N; ++i) {
        if ((solver.solution_set >> i) & 1) cout << i << ' ';
    }
    cout << '\n';
}
Back to top page