codeforces 1206D. Shortest Cycle

这里 

D. Shortest Cycle

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given nn integer numbers a1,a2,…,ana1,a2,…,an. Consider graph on nn nodes, in which nodes ii, jj (i≠ji≠j) are connected if and only if, aiaiAND aj≠0aj≠0, where AND denotes the bitwise AND operation.

Find the length of the shortest cycle in this graph or determine that it doesn't have cycles at all.

Input

The first line contains one integer nn (1≤n≤105)(1≤n≤105) — number of numbers.

The second line contains nn integer numbers a1,a2,…,ana1,a2,…,an (0≤ai≤10180≤ai≤1018).

Output

If the graph doesn't have any cycles, output −1−1. Else output the length of the shortest cycle.

Examples

input

Copy

4
3 6 28 9

output

Copy

4

input

Copy

5
5 12 9 16 48

output

Copy

3

input

Copy

4
1 2 4 8

output

Copy

-1

Note

In the first example, the shortest cycle is (9,3,6,28)(9,3,6,28).

In the second example, the shortest cycle is (5,12,9)(5,12,9).

The graph has no cycles in the third example.

弗洛伊德找最短的环,如果不为0的个数比128个多那么就是3。然后就可以暴力了因为数据量控制在很小。为什么是128呢首先数据范围是10^18可以用64位二进制表示而且运算结果不为0表示相同位置为1如果相同位置1的个数大于三那么最短的环肯定就是3,然然后根据 鸽巢原理 64个数(不为0的数但是可以相同)那么每个位置上1的个数至少为1,相同128每个位置上至少2个1如果说超过了128那肯定就是3啦。

枚举每两个本来就可以链接的点然后把它们之间的距离置为正无穷这样就可以用其他的点去更新一个新的“最短路”这样最短路的长度+1就是最短环点的个数。数据范围比较大ll别忘了开。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m,d[300][300],use[200][200];
ll a[200000];
const ll inf=1e10;
int main()
{
    int n=0;
    cin>>m;
    for(int i=1; i<=m; i++)
    {
        ll x;
        cin>>x;
        if(x!=0)
            a[++n]=x;
    }
    if(n>120)
        cout<<3<<endl;
    else if(n<3)
        cout<<-1<<endl;
    else
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                use[i][j]=(a[i]&a[j]);
            }
        }
        ll ans=inf;
        for(int k=1; k<=n; k++)
            for(int l=k+1; l<=n; l++)
            {
                if(use[k][l]==0)
                    continue;
                for(int i=1; i<=n; i++)
                {
                    for(int j=1; j<=n; j++)
                    {
                        d[i][j]=use[i][j]==0?inf:1;
                    }
                    d[i][i]=inf;
                }
                d[k][l]=d[l][k]=inf;

                for(int m=1;m<=n;m++)
                {
                    for(int i=1;i<=n;i++)
                    {
                        for(int j=1;j<=n;j++)
                        {
                            if(i!=j&&i!=m&&j!=m&&d[i][m]<inf&&d[m][j]<inf)
                            {
                                d[i][j]=min(d[i][j],d[i][m]+d[m][j]);
                            }
                        }
                    }
                }
                ans=min(ans,d[k][l]+1);
            }
        if(ans<inf)
            cout<<ans<<endl;
        else
            cout<<-1<<endl;


    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值