zoukankan      html  css  js  c++  java
  • Codeforces 576D. Flights for Regular Customers(倍增floyd+bitset)

      这破题调了我一天...错了一大堆细节T T

      首先显然可以将边权先排序,然后逐个加进图中。

      加进图后,倍增跑跑看能不能到达n,不能的话加新的边继续跑。

      倍增的时候要预处理出h[i]表示转移矩阵的2^0~i的或和,转移是h[i]=h[i-1]*h[i-1]。

      注意两个矩阵包含0~i和0~j相乘的时候,得到的矩阵是0~i*j的,而两个矩阵包含0~i和0~j或起来的时候,得到的矩阵是j~i+j的。

      倍增的时候因为必须答案单调,所以当前的值必须或上之前的值。

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<bitset>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int maxn=160, inf=1e9+160;
    struct mtx{bitset<maxn>mp[maxn]; mtx(){for(int i=0;i<maxn;i++) mp[i].reset();}}tmp, tmp2, f, base, h[35];
    struct poi{int x, y, dis;}a[maxn];
    int n, m;
    mtx operator *(mtx a, mtx b)
    {
        mtx c;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        if(a.mp[i][j]) c.mp[i]|=b.mp[j];
        return c;
    }
    mtx operator |(mtx a, mtx b)
    {
        mtx c; 
        for(int i=1;i<=n;i++)
        c.mp[i]|=a.mp[i]|b.mp[i];
        return c;
    }
    inline void power(int b)
    {
        if(b<=0) return;
        for(;b;b>>=1, tmp=tmp*tmp)
        if(b&1) f=f*tmp;
    }
    inline bool cmp(poi a, poi b){return a.dis<b.dis;}
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i=1;i<=m;i++) scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].dis);
        sort(a+1, a+1+m, cmp); a[m+1].dis=inf;
        if(a[1].dis) return puts("Impossible"), 0;
        for(int i=1;i<=n;i++) f.mp[i][i]=1;
        for(int i=1;i<=m;i++)
        {
            tmp=base; power(a[i].dis-a[i-1].dis);
            base.mp[a[i].x][a[i].y]=1;
            int up=log2(a[i+1].dis-a[i].dis);
            h[0]=base; for(int j=1;j<=n;j++) h[0].mp[j][j]=h[0].mp[j][j]|1;
            mtx tmpx; for(int j=1;j<=n;j++) tmpx.mp[j][j]=1;
            if(a[i+1].dis-a[i].dis & 1) tmpx=tmpx|(tmpx*h[0]);
            for(int j=1;j<=up;j++) 
            {
                h[j]=h[j-1]*h[j-1];
                if(a[i+1].dis-a[i].dis & (1<<j)) tmpx=tmpx|(tmpx*h[j]);
            }
            tmpx=f*tmpx; 
            if(!tmpx.mp[1][n]) continue;
            mtx tmp1=f; int ans=0;
            for(int j=up;j>=0;j--)
            if(a[i].dis+ans+(1<<j)<=a[i+1].dis)
            {
                tmp2=tmp1; tmp2=tmp2*h[j];
                if(tmp2.mp[1][n]) continue;
                ans+=(1<<j); tmp1=tmp2;
            }
            return printf("%d
    ", a[i].dis+ans+1), 0;
        }
        puts("Impossible");
    }
    View Code
  • 相关阅读:
    (转)静态方法与实例方法
    使用C#和Excel进行报表开发(8)
    js千分位
    各种语言多态性比较
    中国互联网100个Web2.0网站名单
    HDU4405 期望
    HDU1266 字符串逆转
    POJ1087 DInic
    POJ1003 水~
    HDU4403 DFS
  • 原文地址:https://www.cnblogs.com/Sakits/p/8040256.html
Copyright © 2011-2022 走看看