CF 1206D

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
", ans);
            }
            return 0;
}
View Code
原文地址:https://www.cnblogs.com/ckxkexing/p/11379041.html