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\n",ans);
}
/*
3 2
1 2 0
2 3 1

3 3
2 1 0
2 3 6
1 2 0
*/

 

posted @ 2018-06-20 10:58  fcwww  阅读(326)  评论(0编辑  收藏  举报