BZOJ3149 CTSC2013 复原 搜索

传送门


\(N \leq 20\)很适合暴搜……

第二问最大独立集裸题,\(O(2^NN)\)的算法都能过……

考虑第一问,使用搜索寻找可行解

每一次枚举一条弦的两个端点,通过位运算计算与其相交的弦的数量进行剪枝

一些其他的剪枝:

①两个非\(0\)值中间的所有\(0\)的地位是一样的,所以可以将这些\(0\)缩成一个\(0\)

②每一个连通块分别考虑,可以避免大量的重复情况

#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;
 
inline int read(){
    int a = 0;
    char c = getchar();
    bool f = 0;
    while(!isdigit(c) && c != EOF){
        if(c == '-')
            f = 1;
        c = getchar();
    }
    if(c == EOF)
        exit(0);
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return f ? -a : a;
}
 
bitset < 23 > Edge[23] , cur , ans;
int arr[41] , ansArr[41] , times[21] , ind[21] , N , M , len , cntInd , cntA;
bool vis[41];
queue < int > q;
 
bool dfs1(int x){
    if(x > cntInd)
        return 1;
    bitset < 23 > tmp;
    for(int i = 1 ; i < x ; ++i)
        tmp |= 1 << ind[i];
    ++len;
    for(int i = len ; i > 1 ; --i)
        arr[i] = arr[i - 1];
    for(int i = 1 ; i <= len ; ++i){
        arr[i] = ind[x];
        ++len;
        for(int j = len ; j > i + 1 ; --j)
            arr[j] = arr[j - 1];
        bitset < 23 > p;
        p.set();
        for(int j = i + 1 ; j <= len ; ++j){
            arr[j] = ind[x];
            if((p & tmp) == (Edge[ind[x]] & tmp) && dfs1(x + 1))
                return 1;
            arr[j] = arr[j + 1];
            p[arr[j]] = p[arr[j]] ^ 1;
        }
        --len;
        arr[i] = arr[i + 1];
    }
    --len;
    return 0;
}
 
void dfs2(int x){
    if(cur.count() + x <= ans.count())
        return;
    if(!x)
        ans = cur;
    if((Edge[x] & cur) == cur){
        cur.set(x);
        dfs2(x - 1);
        cur.reset(x);
    }
    dfs2(x - 1);
}
 
int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    N = read();
    M = read();
    for(int i = 1 ; i <= N ; ++i){
        Edge[i].set();
        ind[i] = i;
    }
    for(int i = 1 ; i <= M ; ++i){
        int a = read() , b = read();
        Edge[a][b] = Edge[b][a] = 0;
    }
    for(int i = 1 ; i <= N ; ++i)
        if(!vis[i]){
            vis[i] = 1;
            q.push(i);
            ind[cntInd = 1] = i;
            while(!q.empty()){
                int t = q.front();
                q.pop();
                for(int j = 1 ; j <= N ; ++j)
                    if(!vis[j] && !Edge[t][j]){
                        vis[j] = 1;
                        q.push(j);
                        ind[++cntInd] = j;
                    }
            }
            memset(arr , 0 , sizeof(arr));
            if(dfs1(1))
                for(int j = 1 ; j <= cntInd * 2 ; ++j)
                    ansArr[++cntA] = arr[j];
        }
    for(int i = 1 ; i <= N * 2 ; ++i)
        cout << ansArr[i] << ' ';
    cout << endl;
    cur.reset();
    dfs2(N);
    cout << ans.count();
    return 0;
}
posted @ 2019-01-26 09:59  cjoier_Itst  阅读(223)  评论(1编辑  收藏  举报