• bzoj 2165: 大楼【Floyd+矩阵乘法+倍增+贪心】


    1<<i的结果需要是long long的话i是long long是没用的……要写成1ll<<i……我别是个傻子吧
    虽然写的是二进制贪心,但是我觉得二分可能更好写吧(但是会慢)
    首先把矩阵乘法转换成Floyd的形式,注意是进行一次更新,也就是另开一个数组使得更新之后每个[i][j]都变成经过一或两段路,(i,j)之间的最长路
    然后就可以倍增了,一直相乘就会变成经过一二四六八…段路,(i,j)之间的最长路,这里把倍增过程记下来
    直到某次相乘之后符合要求(也就是[1][x]的最长路大于等于m)
    然后按照二进制位从大到小贪心,扫倍增过程能乘就乘,然后再答案上加上1ll<<i
    最后答案要+1

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=105;
    const long long inf=1e18;
    long long T,n,m;
    struct qwe
    {
        long long a[N][N];
        qwe operator * (const qwe &b) const
        {
            qwe c;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    c.a[i][j]=-inf;
            for(int i=1;i<=n;i++)
                c.a[i][i]=0;
            for(int k=1;k<=n;k++)
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        c.a[i][j]=max(c.a[i][j],a[i][k]+b.a[k][j]);
            return c;
        }
    }f[N];
    long long read()
    {
        long long r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    bool ok(qwe a)
    {
        for(int i=1;i<=n;i++)
            if(a.a[1][i]>=m)
                return 1;
        return 0;
    }
    int main()
    {
        T=read();
        while(T--)
        {
            n=read(),m=read();
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    f[0].a[i][j]=read();
                    if(f[0].a[i][j]==0)
                        f[0].a[i][j]=-inf;
                }
            long long cnt=0,ans=1;
            while(1)
            {
                f[cnt+1]=f[cnt]*f[cnt];
                if(ok(f[++cnt]))
                    break;
            }
            qwe p=f[0];
            for(int i=cnt;i>=0;i--)
            {
                qwe nw=p*f[i];
                if(!ok(nw))
                {
                    ans+=1ll<<i;
                    p=nw;
                }
            }
            printf("%lld
    ",ans+1);
        }
        return 0;
    }
    
  • 相关阅读:
    kafka 常见面试题
    分布式-redis实现分布式锁
    java info信息中打印异常堆栈
    11.盛水最多的容器
    445.两数相加
    328. 奇偶链表
    7中join查询
    Linux基础学习05
    Linux基础学习04
    Linux基础学习03
  • 原文地址:https://www.cnblogs.com/lokiii/p/9249417.html
Copyright © 2020-2023  润新知