• 【CF576D】Flights for Regular Customers(矩乘套路题)


    点此看题面

    • 给定一张(n)个点(m)条边的有向图,你要从(1)号点走到(n)号点。
    • 已知当你走了(d_i)条边之后才能走第(i)条边。
    • 问最少要走多少条边才能到达(n)号点。
    • (n,mle150,d_ile10^9)

    矩乘套路题

    考虑(n,m)这么小,(d_i)又这么大,一看就是矩乘的范围了。

    于是考虑用矩阵维护每个点是否可到达,把每条已经能走的有向边表示到转移矩阵上去。

    至于这种取关键点的做法应该也很套路了。就是先把所有边按(d_i)排个序,然后每次矩阵快速幂做一下相邻两个(d_i)中间的转移(即求出恰好走过(d_i)条边之后能走到的点集),接着修改转移矩阵。

    当做到某一条边的时候发现已经能走到(n)了,就从上一条边的状态开始暴力走(n)步。因为在图固定不变时(1)号点到(n)号点的最短路长度显然不可能超过(n)

    但这样的复杂度不太对劲,需要优化。

    (bitset)优化矩乘

    又是另一个套路了。

    考虑这里矩阵维护的是一个点能否到达,也就是说只有(0/1)

    那么我们就可以(bitset)优化,这样就能过了。

    代码:(O(frac{n^3mlogd_i}{32}))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 150
    using namespace std;
    int n,m;struct line {int x,y,t;I bool operator < (Con line& o) Con {return t<o.t;}}s[N+5];
    struct M
    {
    	bitset<N+5> a[N+5],b[N+5];I M() {for(RI i=1;i<=n;++i) a[i].reset(),b[i].reset();}
    	I void Set(CI x,CI y) {a[x].set(y),b[y].set(x);}
    	I M operator * (Con M& o) Con//bitset优化矩乘
    	{
    		M t;for(RI i=1;i<=n;++i) for(RI j=1;j<=n;++j) (a[i]&o.b[j]).any()&&(t.Set(i,j),0);return t;
    	}
    }O,S,U;
    I void QP(RI y) {M x=U;W(y) y&1&&(S=S*x,0),x=x*x,y>>=1;}//矩阵快速幂
    int main()
    {
    	RI i;for(scanf("%d%d",&n,&m),i=1;i<=m;++i) scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].t);
    	RI t=0;for(S.Set(1,1),O=S,sort(s+1,s+m+1),i=1;i<=m;O=S,t=s[i++].t)
    		if(QP(s[i].t-s[i-1].t),U.Set(s[i].x,s[i].y),S.a[1].test(n)) break;//能到达n号点就结束循环
    	for(i=1;i<=n&&!O.a[1].test(n);++i) O=O*U,++t;//从上一条边开始暴力走n步
    	return O.a[1].test(n)?printf("%d
    ",t):puts("Impossible"),0;
    }
    
  • 相关阅读:
    HDU 3853 LOOPS:期望dp【网格型】
    SGU 495 Kids and Prizes:期望dp / 概率dp / 推公式
    BZOJ 1629 [Usaco2005 Nov]Cow Acrobats:贪心【局部证明】
    BZOJ 3400 [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队:dp【和为f的倍数】
    BZOJ 1685 [Usaco2005 Oct]Allowance 津贴:贪心【给硬币问题】
    codeforces-473D Mahmoud and Ehab and another array construction task (素数筛法+贪心)
    poj1964最大子矩阵 (单调栈加枚举)
    poj3111 选取物品(二分+贪心)
    codeforces-777E Hanoi Factory (栈+贪心)
    poj3040 发工资(贪心)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF576D.html
Copyright © 2020-2023  润新知