Codeforces Round 580 (Div. 2) D

Codeforces Round #580 (Div. 2) D

标签: Floyd 二进制拆分


题目描述

戳这里

题解

首先对于这种涉及二进制的运算我们容易想到二进制拆分,对于每一位我们开一个$vector$,表示有多少个值这一位为$1$,那么对于$vector[i]$里面的所有值互相都可以连边,即为一个完全图。而题目要求最小环,那么如果$vector.size()>=3$,直接输出$3$即可,否则就建边。
于是问题就转换成求图中最小环(然后YY了一个dfs的假做法卡到自闭)用$Floyd$算法即可求最小环

代码

#include<bits/stdc++.h>
#define N 100010
#define M 1010
#define ll long long
using namespace std;

ll n, bin = 1, maxn, cnt, ans, k, bid;
ll a[N];
int d[M][M], f[M][M];
bool vis[N];
vector<ll> w[M];
map<int, int> m;

int main()
{
    scanf("%I64d", &n);
    for(int i = 1; i <= n; i ++)
    {
        scanf("%I64d", &a[i]);
        maxn = max(a[i], maxn);
    }
    while(bin <= maxn) bin <<= 1, cnt ++;
    ll b = 1;
    for(int j = 0; j < cnt; j ++, b *= 2)
        for(int i = 1; i <= n; i ++)
            if(a[i] & b) w[j].push_back(i);
    for(int i = 0; i < cnt; i ++)
        if(w[i].size() > 2) {printf("3"); return 0;}
    memset(d, 0x3f3f3f3f, sizeof(d));
    memset(f, 0x3f3f3f3f, sizeof(f));
    for(int i = 0; i < cnt; i ++)
    {
        if(w[i].size() < 2) continue;
        int u = w[i][0], v = w[i][1];
        if(!m[u]) m[u] = ++ bid;
        if(!m[v]) m[v] = ++ bid;
        d[m[u]][m[v]] = d[m[v]][m[u]] = 1;
        f[m[u]][m[v]] = f[m[v]][m[u]] = 1;
    }
    for(int i = 1; i <= bid; i ++)
        d[i][i] = 0;
    ans = 1061109567;
    for(int k = 1; k <= bid; k ++)
    {
        for(int i = 1; i < k; i ++)
            for(int j = 1; j < k; j ++)
            {
                if(i == j) continue;
                ans = min(ans, (ll)f[i][k] + f[k][j] + d[i][j]);
            }
        for(int i = 1; i <= bid; i ++)
            for(int j = 1; j <= bid; j ++)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    }
    if(ans == 1061109567) printf("-1\n");
    else printf("%I64d\n", ans);
    return 0;
}

心得

图论的知识好菜啊QAQ


 上一篇
Insertion Sort Insertion Sort
Insertion Sort标签: 数学 题目描述戳这里 题解首先我们可以分$LIS$为$n$和$n-1$两种情况。对于$LIS$为$n$的情况很简单,只能将$1-k$放在前$k$个位置,答案为${A_{k}}^{k}$现在我们来讨论$L
2019-08-23
下一篇 
Cubes UVALive - 7708 Cubes UVALive - 7708
Cubes UVALive - 7708标签: 搜索 题目描述戳这里题目大意:给你一个数$n$,要求将$n$分解成$m$个数的立方和,要求$m$最小且输出方案 题解很容易能想到这道题可以用记忆化搜索,设$f[i]$表示数字为$i$时最少分
2019-08-18