1. 程式人生 > 其它 >D. Shortest Cycle (最小環&鳩巢原理)

D. Shortest Cycle (最小環&鳩巢原理)

技術標籤:最短路

D. Shortest Cycle (最小環&鳩巢原理)


題意
給定 n ( n ≤ 1 0 5 ) n (n\le 10^5) n(n105)個數 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} ai1018,也就是最多有
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; }