题目来源:http://codeforces.com/contest/1206/problem/D
题意:找到最小的可以形成回路的环,如果两者&操作不为0则有边;
因为1e18,二进制最多也就60位,所以先找出不为0的tot个数,如果tot大于180,必有三个数能够成环(一位上为1其他为0)。之后缩短数据之后就能够使用floyed最小环(打个板子)去判定了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
ll a[200100];
ll mp[205][205],dis[205][205];
int main()
{
ll n,i,j;
scanf("%I64d",&n);
ll hh,tot=0;
for(i=0;i<n;i++)
{
scanf("%I64d",&hh);
if(hh!=0)
{
a[++tot]=hh;
}
}
if(tot>=200)
{
printf("3");
return 0;
}
for(i=1;i<=tot;i++)
{
for(j=1;j<=tot;j++)
{
mp[i][j]=dis[i][j]=INF;
}
}
for(i=1;i<=tot;i++)
for(j=i+1;j<=tot;j++)
{
if(a[i]&a[j])
mp[i][j]=mp[j][i]=dis[i][j]=dis[j][i]=1;
}
ll res=INF;
for(ll k=1;k<=tot;k++)
{
for(ll i=1;i<k;i++)
for(ll j=i+1;j<k;j++)
if(dis[i][j]!=INF&&mp[i][k]!=INF&&mp[k][j]!=INF)
res=min(res,dis[i][j]+mp[i][k]+mp[k][j]);
for(ll i=1;i<=tot;i++)
for(ll j=1;j<=tot;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
if(res==INF)
printf("-1");
else
printf("%I64d",res);
return 0;
}