• CF_576D_Flights for Regular Customers_矩阵乘法+倍增floyd+bitset+bfs


    CF_576D_Flights for Regular Customers_矩阵乘法+倍增floyd+bitset

    https://www.luogu.org/problemnew/show/CF576D


    按d排序,然后对于两个相邻的d,设map[i][j][k]表示从i到j走k步能否走到。

    走di-di-1步可以用矩乘优化一下。

    对于1和n连通的所有情况,跑一遍bfs,取min即可获得答案。

    需要加bitset。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <bitset>
    using namespace std;
    int vis[160],Q[160],l,r,dis[160];
    int n,m,a[160][160];
    struct Mat {
        bitset<151>v[151];
        Mat operator * (const Mat &x) const {
            Mat re;int i,j;
            for(i=1;i<=n;i++) {
                for(j=1;j<=n;j++) {
                    if(v[i][j]) re.v[i]|=x.v[j];
                }
            }
            return re;
        }
    }MAP,RE;
    void Qp(int y) {
        int i,j;
        for(i=1;i<=n;i++) for(j=1;j<=n;j++) MAP.v[i][j]=a[i][j];
        for(;y;y>>=1,MAP=MAP*MAP) {
            if(y&1) RE=RE*MAP;
        }
    }
    struct A {
        int x,y,z;
        bool operator < (const A &u) const {
            return z<u.z;
        }
    }e[160];
    bool bfs() {
        l=r=0; memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis));
        int i;
        for(i=1;i<=n;i++) if(RE.v[1][i]) Q[r++]=i,vis[i]=1;
        while(l<r) {
            int x=Q[l++];
            for(i=1;i<=n;i++) {
                if(a[x][i]&&!vis[i]) {
                    vis[i]=1; Q[r++]=i; dis[i]=dis[x]+1;
                }
            }
        }
        return vis[n];
    }
    int main() {
        scanf("%d%d",&n,&m);
        int i,j=0;
        for(i=1;i<=m;i++) {
            scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
        }
        sort(e+1,e+m+1);
        int lst=0,ans=1<<30; RE.v[1][1]=1;
        while(1) {
            // puts("FUCK");
            for(i=j+1;i<=m;i++) {
                if(e[i].z>lst) break;
                a[e[i].x][e[i].y]=1; j++;
            }
            if(bfs()) ans=min(ans,lst+dis[n]);
            if(j==m) break;
            Qp(e[j+1].z-lst);
            lst=e[j+1].z;
        }
        // for(i=1;i<=n;i++) {for(j=1;j<=n;j++) printf("%d ",RE.v[i][j]==1);puts("");}
        if(ans==1<<30) puts("Impossible");
        else printf("%d
    ",ans);
    }
    /*
    3 2
    1 2 0
    2 3 1
    
    3 3
    2 1 0
    2 3 6
    1 2 0
    */
    
  • 相关阅读:
    【One by one系列】一步步开始使用Redis吧(一)
    Double.valueOf()与Double.parseDouble()两者的区别
    eclipse配置SVN
    java中String.valueOf(obj)、(String)obj与obj.toString()有什么区别
    zookeeper+dubbo【转载】
    jquery中的attr与prop
    window上安装rabbitMQ
    控制 输入框 只能输入数字、小数、负数
    关于JavaScript的事件触发
    JavaScript学习第四天
  • 原文地址:https://www.cnblogs.com/suika/p/9202723.html
Copyright © 2020-2023  润新知