• Codeforces 1206D


    Description

    思路

    首先先给集合里面的数分个组,将二进制中第i位为1的数分到第i组。显然,在同一组的所有数中,两两相与均不为0,故同一组的数全部都需要连边。
    一个环的长度至少为3,所以一旦有一个组里面数的个数大于等于3,那么答案就是3。
    否则,每一组当中个数至多为2,而且它们之间需要连边。因此就可以建一个图了,答案就是图中长度最小的环。
    由于位数不超过60,每组个数不超过2,所以结点数最多为120,可以用Floyed算法求最小环。

    一开始不会求最小环,写了好久乱搞算法,好气哦。
    Floyed算法求最小环,参考至oi-wiki

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <vector>
    #include <set>
    
    using namespace std;
    #define endl '
    '
    typedef long long ll;
    const int N = 200000;
    #define inf 0x3f3f3f3f
    ll arr[N];
    vector<ll> num[100];
    vector<ll>::iterator nend;
    bool more[N];
    ll val[400][400];
    ll dis[400][400];
    int cnt[400];
    vector<ll> ind;
    
    int find(ll val) {
        return lower_bound(ind.begin(), nend, val) - ind.begin() + 1;
    }
    
    int work() {
        int n = ind.size();
        ll ans = inf;
        for(int k = 1; k <= n; k++) {
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                    if(i != j) ans = min(dis[i][j] + val[i][k] + val[k][j], ans);
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                    if(i != j) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
        }
        return ans;
    }
    
    int main() {
        int n;
        cin >> n;
        for(int i = 1; i <= n; i++) {
            cin >> arr[i];
        }
        for(int i = 0; i < 60; i++) {
            for(int j = 1; j <= n; j++) {
                if( ( arr[j]  &  (1ll << i) ) ) {
                    num[i].push_back(arr[j]);
                    ind.push_back(arr[j]);
                }
            }
            if(num[i].size() >= 3) {        
                cout << 3 << endl;
                return 0;
            }
        }
        for(int i = 0; i <= 300; i++) {
            for(int j = 0; j <= 300; j++) {
                val[i][j] = inf;
                dis[i][j] = inf;
            }
        }
        sort(ind.begin(), ind.end());
        nend = unique(ind.begin(), ind.end());
        for(int i = 0; i < 60; i++) {
            if(num[i].size() <= 1) continue;
            int u, v;
            u = find(num[i][0]);
            v = find(num[i][1]);
            if(u == v) more[u] = 1;
            else {
                cnt[u]++;
                cnt[v]++;
                val[u][v] = val[v][u] = 1;
                dis[u][v] = dis[v][u] = 1;
            }
            if((cnt[u] && more[u]) || (cnt[v] && more[v])) { //对有重复元素的特判    
                cout << 3 << endl;
                return 0;
            }
        }
        int ans = work();
        cout << (ans == inf ? -1 : ans) << endl;
    
    }
    
  • 相关阅读:
    EasyHook库系列使用教程之四钩子的启动与停止
    inputclean插件的使用方法
    机器学习(十三)——机器学习中的矩阵方法(3)病态矩阵、协同过滤的ALS算法(1)
    &lt;LeetCode OJ&gt; 204. Count Primes
    leetcode 235: Lowest Common Ancestor of a Binary Search Tree
    数据结构经常使用算法
    调侃物联网开源框架,我们什么时候也来开源一个?
    字符编码简单介绍
    PriorityQueue ,ArrayList , 数组排序
    从struts2.1开始Convention零配置
  • 原文地址:https://www.cnblogs.com/limil/p/12755669.html
Copyright © 2020-2023  润新知