Codeforces Round #580 (Div. 2)D. Shortest Cycle

题目来源:http://codeforces.com/contest/1206/problem/D

题意:找到最小的可以形成回路的环,如果两者&操作不为0则有边;

因为1e18,二进制最多也就60位,所以先找出不为0的tot个数,如果tot大于180,必有三个数能够成环(一位上为1其他为0)。之后缩短数据之后就能够使用floyed最小环(打个板子)去判定了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
ll a[200100];
ll mp[205][205],dis[205][205];
int main()
{
	ll n,i,j;
	scanf("%I64d",&n);
	ll hh,tot=0;
	for(i=0;i<n;i++)
	{
		scanf("%I64d",&hh);
		if(hh!=0)
		{
			a[++tot]=hh;
		}
	 } 
	 if(tot>=200)
	 {
	 	printf("3");
		 return 0; 
	 }
	 for(i=1;i<=tot;i++)
	 {
	 	for(j=1;j<=tot;j++)
	 	{
	 		mp[i][j]=dis[i][j]=INF;
		 }
	 }
	for(i=1;i<=tot;i++)
   	 for(j=i+1;j<=tot;j++)
        {
            if(a[i]&a[j]) 
			mp[i][j]=mp[j][i]=dis[i][j]=dis[j][i]=1;
        }
        ll res=INF;
        for(ll k=1;k<=tot;k++)
		{
            for(ll i=1;i<k;i++)
                for(ll j=i+1;j<k;j++)
                if(dis[i][j]!=INF&&mp[i][k]!=INF&&mp[k][j]!=INF)
                res=min(res,dis[i][j]+mp[i][k]+mp[k][j]);
            for(ll i=1;i<=tot;i++)
                for(ll j=1;j<=tot;j++)
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        }
             if(res==INF)
			  printf("-1");
        	else
			printf("%I64d",res);
	return 0;
 } 
发布了56 篇原创文章 · 获赞 17 · 访问量 2338

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/100064991