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
  • 相关阅读:
    HDU 1022 Train Problem I
    HDU 1702 ACboy needs your help again!
    HDU 1294 Rooted Trees Problem
    HDU 1027 Ignatius and the Princess II
    HDU 3398 String
    HDU 1709 The Balance
    HDU 2152 Fruit
    HDU 1398 Square Coins
    HDU 3571 N-dimensional Sphere
    HDU 2451 Simple Addition Expression
  • 原文地址:https://www.cnblogs.com/Sakits/p/8040256.html
Copyright © 2011-2022 走看看