D. Shortest Cycle (最小環&鳩巢原理)
阿新 • • 發佈:2020-12-24
技術標籤:最短路
D. Shortest Cycle (最小環&鳩巢原理)
題意
給定
n
(
n
≤
1
0
5
)
n (n\le 10^5)
n(n≤105)個數
a
i
a_i
ai,若
a
i
&
a
j
≠
0
a_i\& a_j\neq0
ai&aj=0則,
a
i
,
a
j
a_i,a_j
ai,aj連有一條權為1的邊,求最小環的長度,這裡的最小環的點個數至少為
3
3
3。
思路
鳩巢原理,因為
a
i
≤
1
0
18
a_i\le 10^{18}
ai≤1018,也就是最多有
64
64
64位,我們記
a
i
≠
0
a_i\neq 0
ai=0得個數有
c
n
t
cnt
cnt個,當
c
n
t
>
64
×
2
cnt>64\times 2
cnt>64×2時,肯定有一位為
1
1
1的數最少有3個,這樣就滿足了一個三元環。
否則:就直接暴力跑 f l o y d floyd floyd最小環即可。
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=2e4+5,inf=1e8,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int n,c;
ll a[N],b[N];
int g[200][200],d[200][200],ans=inf;
void floyd(){
for(int k=1;k<=c;k++){
for(int i=1;i<k;i++)
for(int j=i+1;j<k;j++) ans=min(ans,d[i][j]+g[i][k]+g[k][j]);
for(int i=1;i<=c;i++ ) if(d[i][k]!=inf)
for(int j=1;j<=c;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(a[i]!=0) b[++c]=a[i];
}
if(c>128) printf("3\n");
else {
for(int i=1;i<=c;i++)
for(int j=1;j<=c;j++) if(i!=j) g[i][j]=g[j][i]=d[i][j]=d[j][i]=((b[i]&b[j])>0)?1:inf;
floyd();
if(ans==inf) printf("-1\n");else printf("%d\n",ans);
}
return 0;
}