分析: 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; }