• 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;
    }
    
  • 相关阅读:
    前端开发聚合
    6. webRTC
    14.移动端图片浏览组件 react-wx-images-viewer
    windows下怎样使用md命令一次建立多级子目录
    mysql打印输出转csv格式
    Java Stream简介, 流的基本概念
    Linux使用Shell脚本实现ftp的自动上传下载
    在Linux中设置UMASK值
    SFTP+OpenSSH+ChrootDirectory设置
    导出php5.4支持的数组格式,即以[]为标识符而不是以array()标识
  • 原文地址:https://www.cnblogs.com/Itst/p/10322647.html
Copyright © 2020-2023  润新知