CF1205B Shortest Cycle(Floyd判最小环)

满分做法:

因为每个数都小于(10^{18}),因此每个数最多有(64)位,因此如果有超过(128)个非零数字,那么必定有一位在(3)个及以上个数的二进制表示下为(1),所以最小环大小为(3)

当n<=128时,直接Floyd判最小环。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxm=1e5+7;
int n;
ll a[maxm];
int dis[133][133];
int len[133][132];
int ans=1e9+7;
void Floyd()
{
 for(int k=1;k<=n;k++)
 {
  for(int i=1;i<=n;i++)
  {
   for(int j=i+1;j<=n;j++)
   {
   	 if(i==j||i==k||j==k) continue;
   	 ans=min((ll)ans,(ll)dis[i][j]+(ll)len[i][k]+(ll)len[k][j]);
   }
  }
  for(int i=1;i<=n;i++)
  {
   for(int j=1;j<=n;j++)
   {
    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
   }
  }
 }
}
int main()
{
 memset(dis,63,sizeof(dis));
 memset(len,63,sizeof(len));
 scanf("%d",&n);
 for(int i=1;i<=n;i++)
 {
  scanf("%lld",&a[i]);
  if(!a[i]) n--,i--;//注意a[i]==0时必不会有连边,直接去除,使剩下的达到128 
 }
 if(n>=128)
 printf("3
");
 else
 {
  for(int i=1;i<=n;i++)
  {
    for(int j=1;j<=n;j++)
    {
     if((a[i]&a[j])!=0&&i!=j)
	 len[i][j]=dis[j][i]=1;	
    }
  }
  Floyd();
  if(ans==1e9+7)
  printf("-1
");
  else 
  printf("%d
",ans);
 }
 return 0;	
}
原文地址:https://www.cnblogs.com/lihan123/p/11694982.html