bzoj 1770 [Usaco2009 Nov]lights 燈 meet in the middle

题面

题目传送门

解法

题解里都是高斯消元然后dfs,蒟蒻表示不会

直接分两半dfs即可

时间复杂度:\(O(2^{\frac{n}{2}})\)

代码

#include <bits/stdc++.h>
#define LL long long
#define N 110
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int ans; LL s[N];
vector <int> e[N];
map <LL, int> h;
void dfs1(int x, int n, int sum, LL tmp) {
    if (x > n) {
        h[tmp] = sum;
        return;
    }
    dfs1(x + 1, n, sum + 1, tmp ^ s[x]);
    dfs1(x + 1, n, sum, tmp);
}
void dfs2(int x, int n, int sum, LL tmp) {
    if (x > n) {
        LL y = ((1ll << n) - 1) ^ tmp;
        if (h.count(y)) chkmin(ans, h[y] + sum);
        return;
    }
    dfs2(x + 1, n, sum + 1, tmp ^ s[x]);
    dfs2(x + 1, n, sum, tmp);
}
int main() {
    int n, m; read(n), read(m);
    for (int i = 1; i <= m; i++) {
        int x, y; read(x), read(y);
        s[x] |= 1ll << y - 1;
        s[y] |= 1ll << x - 1;
    }
    for (int i = 1; i <= n; i++) s[i] |= 1ll << i - 1;
    dfs1(1, n / 2, 0, 0);
    ans = INT_MAX; dfs2(n / 2 + 1, n, 0, 0);
    cout << ans << "\n";
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/copperoxide/p/9476736.html