D. Shortest Cycle(floyd最小环)

D. Shortest Cycle
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given nn integer numbers a1,a2,,ana1,a2,…,an. Consider graph on nn nodes, in which nodes ii, jj (iji≠j) are connected if and only if, aiaiAND aj0aj≠0, where AND denotes the bitwise AND operation.

Find the length of the shortest cycle in this graph or determine that it doesn't have cycles at all.

Input

The first line contains one integer n(1n105)(1≤n≤105) — number of numbers.

The second line contains nn integer numbers a1,a2,,ana1,a2,…,an (0ai10180≤ai≤1018).

Output

If the graph doesn't have any cycles, output 1−1. Else output the length of the shortest cycle.

Examples
input
4
3 6 28 9
output
4
input
5
5 12 9 16 48
output
3
input
4
1 2 4 8
output
-1
Note

In the first example, the shortest cycle is (9,3,6,28)(9,3,6,28).

In the second example, the shortest cycle is (5,12,9)(5,12,9).

The graph has no cycles in the third example.

算法:floyd最小环

题解:根据题意建图,跑最小环模板。

#include <iostream>
#include <cstdio>

using namespace std;

#define INF 0x3f3f3f3f
const int maxn = 1e5+7;

typedef long long ll;

int n;
ll arr[maxn];
ll dis[200][200];
ll maze[200][200];

int floyd() {
    ll res = INF;
    for(int k = 1; k <= n; k++) {
        //下面两个循环先算res的原因是:你从i~j的最短路还没有经过k
        //其实就是我先不管i~k,k~i这条边(等同于删除),然后找到i~j这条边的权值,再加上i~k,k~j这条边就是一个环了,找到最小的情况
        for(int i = 1; i < k; i++) {    
            for(int j = i + 1; j < k; j++) {
                res = min(res, dis[i][j] + maze[i][k] + maze[k][j]);
            }
        }
        //这个循环就是floyd更新多源最短路
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
            }
        }
    }
    return res;
}

int main() {
    scanf("%d", &n);
    int k = 0;
    for(int i = 1; i <= n; i++) {
        ll x;
        scanf("%I64d", &x);
        if(x != 0) {    //将0去掉,0按位与任何数就是0,不存在有这种情况的环
            arr[++k] = x;
        }
    }
    n = k;
    if(n > 3 * 64) {    //因为每位数最多64位,因为没有0,所以这64位上,必定有有一位有值,当同一位的值超过3时,最小环就由这三个数组成
        printf("3
");
        return 0;
    }
    //建图
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(arr[i] & arr[j]) {
                dis[i][j] = dis[j][i] = maze[i][j] = maze[j][i] = 1;
            } else {
                dis[i][j] = dis[j][i] = maze[i][j] = maze[j][i] = INF;
            }
        }
    }
    int ans = floyd();
    if(ans == INF) {    //没有形成环
        printf("-1
");
    } else {
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/buhuiflydepig/p/11375682.html