CF 1206D - Shortest Cycle Floyd求最小环

Shortest Cycle

题意

有n(n <= 100000)个数字,两个数字间取&运算结果大于0的话连一条边。问图中的最小环。

思路

可以发现当非0数的个数很大,比如大于200时,一定存在长度为3的环。

如果小于200, 我们就用到了Floyd求最小环的技巧。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr << #x << " := " << x << endl;
#define bug cerr << "-----------------------" << endl;
#define FOR(a, b, c) \
    for (int a = b; a <= c; ++a) 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template <typename T>
inline T read(T &x) {
    x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x = f ? -x : x;
}
/**********showtime************/
const int maxn = 2e5 + 9;
ll a[maxn];
int cnt[20];
ll ans;
ll dp[209][209], g[209][209];
vector<ll> b;

int main() {
    int n;
    scanf("%d", &n);
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
        if (a[i] == 0)
            cnt++;
        else
            b.pb(a[i]);
    }
    if (n - cnt > 200)
        puts("3");
    else {
        int n = b.size();
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i == j)
                    dp[i][j] = 0, g[i][j] = 0;
                else
                    dp[i][j] = dp[j][i] = inf, g[i][j] = inf;
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if ((b[i] & b[j]) > 0) {
                    dp[i + 1][j + 1] = 1;
                    dp[j + 1][i + 1] = 1;
                    g[i + 1][j + 1] = 1;
                    g[j + 1][i + 1] = 1;
                }
            }
        }
        ans = inf;
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i < k; i++) {
                for (int j = i + 1; j < k; j++) {
                    ans = min(ans, dp[i][j] + g[k][i] + g[k][j]);
                }
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
                }
            }
        }
        if (ans == inf)
            puts("-1");
        else
            printf("%lld\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2019-08-19 19:11  ckxkexing  阅读(211)  评论(0编辑  收藏  举报