zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第二场)- Kth Minimum Clique

    优先队列bfs + 状态压缩

    不难想到,最小团就是空集,我们可以向这个空集里加点,来找到k小团

    具体做法就是用优先队列,把权值小的团出队,为了不重复加点,我们可以记录一下最后几个被加进团的点,这样下次直接从该点之后遍历,这样就可以把所有点都遍历一次了。

    用bitset来保存点连接状态可以直接判断该点是否与团的每个点相连

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
    using namespace std;
    typedef long long LL;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int ret = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            ret = (ret << 3) + (ret << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -ret : ret;
    }
    inline int lcm(int a, int b){ return a / __gcd(a, b) * b; }
    template <typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 200;
    int n, k, val[N];
    
    struct Node{
        LL w;
        int s;
        bitset<105> clique;
        bool operator < (const Node &rhs) const {
            return w > rhs.w;
        }
        Node(){}
        Node(LL w, int s, bitset<105> clique): w(w), s(s), clique(clique){}
    };
    
    bitset<105> e[N];
    
    LL solve(){
        priority_queue<Node> pq;
        int cnt = 0;
        bitset<105> raw;
        raw.reset();
        pq.push(Node(0, 0, raw));
        while(!pq.empty()){
            Node cur = pq.top(); pq.pop();
            cnt ++;
            if(cnt == k) return cur.w;
            for(int i = cur.s + 1; i <= n; i ++){
                if((e[i] & cur.clique) == cur.clique){
                    bitset<105> b(cur.clique);
                    b.set(i, 1);
                    pq.push(Node(cur.w + val[i], i, b));
                }
            }
        }
        return -1;
    }
    
    int main(){
    
        n = read(), k = read();
        for(int i = 1; i <= n; i ++) val[i] = read();
        string s;
        for(int i = 1; i <= n; i ++){
            cin >> s;
            for(int j = 1; j <= n; j ++){
                e[i].set(j, s[j - 1] - '0');
            }
        }
        printf("%lld
    ", solve());
        return 0;
    }
    
  • 相关阅读:
    VC++界面编程个性化你的工具栏图标(转)
    C/C++指令 #undef ,#ifdef, #ifndef,#if的用法(转)
    为自定义工具栏按钮添加消息响应函数
    VC++深入详解:函数的重载 (转)
    NP和P问题
    How To Compile A Kernel The Ubuntu Way
    【转】关闭对话框,OnClose和OnCancel MFC中屏蔽ESC和回车关闭对话框
    MFC学习笔记之ClassWizard
    《c专家编程》学习笔记一
    <转>C语言中的文件输入输出函数
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/11222578.html
Copyright © 2011-2022 走看看