有 (n(nleq 10^5)) 个数 (a_1,...,a_n (aleq 10^{18})) 。有一个图用这个方法生成,若 (a_i) 按位与 (a_j) 不为 (0),则在 (a_i,a_j) 间连一条无向边。求这个图的最小环,若无环输出 (-1)。
Solution
把 (a_i=0) 的数字删掉
当 (n ge 128) 时,至少有一个二进制位满足该位为 (1) 的数个数 (ge 3),即形成三元环
当 (n<128) 时,暴力建图后用 Floyd 跑最小环即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 205;
int n,a[N],g[N][N],f[N][N];
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) {
if(i>128) break;
cin>>a[i];
if(a[i]==0) --i, --n;
}
if(n>=128) {
cout<<3;
return 0;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(i==j) f[i][j]=g[i][j]=0;
else f[i][j]=g[i][j]=(a[i]&a[j]?1:999);
}
}
int ans=999;
for(int k=1;k<=n;k++) {
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) if(i!=j&&j!=k&&i!=k) {
ans=min(ans,f[i][k]+f[k][j]+g[j][i]);
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(g[i][k]+g[k][j] < g[i][j]) {
g[i][j]=g[i][k]+g[k][j];
}
}
}
}
cout<<(ans>=999?-1:ans)<<endl;
}