cf 1205B Shortest Cycle(最小环)

题目链接

首先学习一下抽屉原理:百度百科链接
总结一句话:把多于 m n + 1 m*n+1 (n不为0)个的物体放到n个抽屉里,则至少有一个抽屉里有不少于 m + 1 (m+1) 的物体。

题意:给n个数,在 a i a_i a j a_j 之间建一条权值为1的边当且仅当 a i a_i & a j a_j != 0,问最小环的长度
思路: n n 最多有 1 0 5 10^5 个,暴力存图都不可能开这么大的空间。就要优化,首先0肯定不用加进图中。 a i a^i 最大有 1 0 18 10^{18} ,也就是最大不超过 2 60 2^{60} n n 个数,每个数都有60个位置,只要这60个位置里至少有一个位置上有3个以上的1,那么答案就是3。所以我们需要某个位置上的 1的个数>=3,就把每个数都抽象成1,把 a a 个数填到60个位置中,根据抽屉原理, a a 为121,所以不为0的数只要大于120就直接输出3即可

    #include<bits/stdc++.h>
    #define mid(l,r) (( l + r ) / 2)
    #define lowbit(x) (( x & ( - x )))
    #define lc(root) ((root * 2))
    #define rc(root) ((root * 2 + 1))
    #define me(array,x) (memset( array , x , sizeof( array ) ) )
    typedef long long LL;
    using namespace std;
    const LL inf = 10000000;
    const int mod = 1e9 + 7;
    const int maxn = 1e6 + 10;
    LL mp[500][500], dis[500][500], a[maxn];
    LL n, cnt=0;
     
    void init()
    {
        me(mp,0);
        me(dis,0);
        for(int i=1; i<=cnt; i++)
        {
            for(int j=1; j<=cnt ; j++)
            {
                if(a[i]&a[j])
                    mp[i][j] = dis[i][j] = 1;
                else
                    mp[i][j] = dis[i][j] = inf;
            }
        }
    }
     
    int main()
    {
        scanf("%lld",&n);
        for(int i = 1 ; i <= n ; i++)
        {
            LL x;
            scanf("%lld",&x);
            if(x != 0)
                a[++cnt] = x;
        }
        if(cnt > 120)
            printf("3\n");
        else
        {
            init();
            LL ans  = inf;
            for(int k=1; k<=cnt ; k++)
            {
                for(int i=1; i<k; i++)
                {
                    for(int j=i+1; j<k; j++)
                    {
                        ans = min(ans,mp[i][j] + dis[i][k] + dis[k][j]);
                    }
     
                }
     
                for(int i = 1; i <= cnt ; i++)
                {
                    for(int j =1 ; j <= cnt ; j++)
                    {
                        mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
                    }
                }
            }
            if(ans == inf)
                printf("-1\n");
            else
                printf("%lld\n",ans );
        }
        return 0;
    }
发布了34 篇原创文章 · 获赞 7 · 访问量 1873

猜你喜欢

转载自blog.csdn.net/qq_43628761/article/details/100144504