分析: 10^18可拆为64位,考虑每一位上如果有三个或三个以上的数为1,那么就一定有一个三条边的环。因此每一位最多贡献2条边,否则就一定有环。所以当n>2*64的时候直接输出3即可,128以下直接Floyd求最小环
PS.不知道为什么这题用memset初始化就出问题了,以后还是尽量少碰memset,直接for
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 305;
const ll INF = 0x3f3f3f3f;
ll mp[maxn][maxn],dis[maxn][maxn];//dis为两点之间最短距离,mp为两点之间是否直接相连,相连为1,否则为INF
vector<ll> a;
ll min(ll a,ll b){return a<b?a:b;}
void Floyd()
{
ll ans=INF;
for(int k=0;k<a.size();k++)// Floyd 的 k 必须放在最外面
{
for(int i=0;i<k;i++) for(int j=i+1;j<k;j++)
ans=min(ans,dis[i][j]+mp[i][k]+mp[k][j]);
for(int i=0;i<a.size();i++) for(int j=0;j<a.size();j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
if(ans==INF) printf("-1"); else printf("%I64d",ans);
}
int main()
{
int n; ll x;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%I64d",&x);
if(x) a.push_back(x);
}
if(a.size()>2*64) {
printf("3"); return 0;
}
for(int i=0;i<a.size();i++) for(int j=0;j<a.size();j++) dis[i][j]=mp[i][j]=INF;
for(int i=0;i<a.size()-1;i++) for(int j=i+1;j<a.size();j++)
if(a[i]&a[j]) mp[i][j]=mp[j][i]=dis[i][j]=dis[j][i]=1;
Floyd();
return 0;
} 
京公网安备 11010502036488号