题面传送门

题意:

有一张 \(n\) 个点 \(m\) 条边的有向图,你初始在 \(1\) 号点,边上有边权 \(c_i\) 表示只有当你经过至少 \(c_i\) 条边的时候你才能经过第 \(i\) 条边。

求从 \(1\) 号点开始最少走过多少条边才能到达 \(n\) 号点。

\(n,m \leq 150,c_i\leq 10^9\)

注意到题目中 \(c_i\) 的数据范围可以达到 \(10^9\),我们显然不能一步步枚举可达的位置。

但是 \(m\) 的数据范围很小,说明转移矩阵最多改变 \(150\) 次,这启示我们可以用矩阵乘法

具体来说,我们建立 \(1\times n\) 的矩阵 \(A\),\(A_i\) 表示在当前状态下 \(i\) 是否能够到达(\(0/1\))。

再建立一个 \(n\times n\) 的转移矩阵 \(B\),\(B_{i,j}\) 表示 \(i\) 与 \(j\) 是否有边相连。

那么走一步之后,新的 \(A'_i=\or_{i=1}^nA_k\and B_{k,i}\)

也就是说,如果存在一个点 \(k\) 使得在当前状态下能够到达 \(k\) 并且 \(k\) 与 \(i\) 有直接边相连,那么就可以从 \(k\) 走到 \(i\)。

由于广义矩阵乘法也满足乘法结合律,那么走 \(t\) 步后可达状态为 \(A\times B^t\)

考虑将边按照 \(c_i\) 从小到大排序,然后依次改变转移矩阵 \(B\)

然后做一遍多源 \(bfs\),求出可达的所有点中,到达点 \(n\) 的最短距离。

时间复杂度 \(\mathcal O(n^3m\log c_i)\)。注意到矩阵 \(A,B\) 每一位都是 \(0\) 或 \(1\),矩阵乘法中也只包含位运算,因此可以使用 bitset 优化,时间复杂度 \(\mathcal O(\frac{n^3m\log c_i}{\omega})\) 。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
const int MAXN=150+5;
const int MAXM=150+5;
int n,m,d[MAXN];
struct edge{
int u,v,c;
friend bool operator <(edge a,edge b){
return a.c<b.c;
}
} e[MAXM];
struct mat{
bitset<MAXN> x[MAXN];
friend mat operator *(mat a,mat b){
mat c;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
if(a.x[i][j]) c.x[i]|=b.x[j];//optimize multiplation by bitset
return c;
}
} to,c;
mat qpow(mat x,int e){
mat ret;for(int i=1;i<=n;i++) ret.x[i][i]=1;
while(e){if(e&1) ret=ret*x;x=x*x;e>>=1;}return ret;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
sort(e+1,e+m+1);to.x[1][1]=1;int pre=0,ans=2e9;
for(int i=1;i<=m;i++){
to=to*qpow(c,e[i].c-pre);
pre=e[i].c;c.x[e[i].u][e[i].v]=1;
memset(d,63,sizeof(d));
queue<int> q;for(int j=1;j<=n;j++) if(to.x[1][j]) q.push(j),d[j]=0;
while(!q.empty()){
int cur=q.front();q.pop();
for(int j=1;j<=n;j++) if(c.x[cur][j]&&d[j]>1e9){
d[j]=d[cur]+1;q.push(j);
}
}
if(d[n]<1e9) ans=min(ans,e[i].c+d[n]);
}
if(ans==2e9) puts("Impossible");
else printf("%d\n",ans);
return 0;
}

Codeforces 576D - Flights for Regular Customers(bitset 优化广义矩阵乘法)的更多相关文章

  1. Codeforces 576D Flights for Regular Customers(矩阵加速DP)

    题目链接  Flights for Regular Customers 首先按照$d$的大小升序排序 然后分成$m$个时刻,每条路径一次处理过来. $can[i][j]$表示当前时刻$i$能否走到$j ...

  2. Codeforces 576D Flights for Regular Customers (图论、矩阵乘法、Bitset)

    题目链接 http://codeforces.com/contest/576/problem/D 题解 把边按\(t_i\)从小到大排序后枚举\(i\), 求出按前\((i-1)\)条边走\(t_i\ ...

  3. Codeforces 576D. Flights for Regular Customers(倍增floyd+bitset)

    这破题调了我一天...错了一大堆细节T T 首先显然可以将边权先排序,然后逐个加进图中. 加进图后,倍增跑跑看能不能到达n,不能的话加新的边继续跑. 倍增的时候要预处理出h[i]表示转移矩阵的2^0~ ...

  4. Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP

    题意: 给一个$n$点$m$边的连通图 每个边有一个权值$d$ 当且仅当当前走过的步数$\ge d$时 才可以走这条边 问从节点$1$到节点$n$的最短路 好神的一道题 直接写做法喽 首先我们对边按$ ...

  5. (中等) CF 576D Flights for Regular Customers (#319 Div1 D题),矩阵快速幂。

    In the country there are exactly n cities numbered with positive integers from 1 to n. In each city ...

  6. 576D Flights for Regular Customers

    分析 https://www.cnblogs.com/onioncyc/p/8037056.html 写的好像有点问题 但是大致就是这个意思 代码很好理解 代码 #include<bits/st ...

  7. CF576D Flights for Regular Customers 矩阵乘法 + Bitset优化

    %%%cxhscst2's blog Codeforces 576D Flights for Regular Customers(矩阵加速DP) 代码非常优美 + 简洁,学习到了 Code: #inc ...

  8. 【CodeForces】576 D. Flights for Regular Customers

    [题目]D. Flights for Regular Customers [题意]给定n个点m条边的有向图,每条边有di表示在经过该边前必须先经过di条边,边可重复经过,求1到n的最小经过边数.n,m ...

  9. 「CF576D」 Flights for Regular Customers

    「CF576D」 Flights for Regular Customers 对不起我又想网络流去了 你看这长得多像啊,走过至少多少条边就是流量下界,然后没上界 但是这个题求的最少走多少条边啊...完 ...

随机推荐

  1. GPIO位带操作点亮LED,且使用按键控制开关

    1. 项目 类似与C51单片机的位操作使能引脚来点亮LED. 例如,sbit P0^0 = 0 LED1 = P0^0; 2. 代码 main.c #include "stm32f10x.h ...

  2. SpringMVC、Spring、MyBatis整合(IDEA版)

    1 环境准备 1.1 软件架构 JDK 1.8 Spring 4.x Mybatis 3.x Maven 3.x MySQL 5.7 1.2 创建数据库 创建数据库,数据库名ssm-demo,字符集u ...

  3. 【UE4 设计模式】享元模式 Flyweight Pattern

    概述 描述 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用. 由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻 ...

  4. [no_code]团队任务拆解Alpha

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 团队任务拆解 我们在这个课程的目标是 远程协同工作,采用最新技术开发软件 这个作业在哪个具体方面帮 ...

  5. logstash的mutate过滤器的使用

    logstash的mutate过滤器的使用 一.背景 二.需求 三.实现步骤 1.安装 `csv codec` 插件 2.准备需要读取的文件数据 3.编写 pipeline ,读取和输出数据 4.mu ...

  6. 六个好习惯让你的PCB设计更优

    PCB layout工程师每天对着板子成千上万条走线,各种各样的封装,重复着拉线的工作,也许很多人会觉得是很枯燥无聊的工作内容.看似软件操作搬运工,其实设计人员在过程中要在各种设计规则之间做取舍,兼顾 ...

  7. redis 的单机安装

    redis 单机安装 参考文档地址:https://www.cnblogs.com/withfeel/p/10655994.html 1,下载redis,下载地址http://download.red ...

  8. ant生成jmeter测试报告没有数据【已解决】

    1.如下图,在配置build时,到网上找配置文件,配置样式表文件名经常是jmeter-results-detail-report_21.xsl, 3.但是在其他版本可能被不是这个文件名,在jmeter ...

  9. AppGallery Connect场景化开发实战—注册订阅通知

    借助AppGallery Connect(以下简称AGC)的认证服务,云函数,短信服务等服务,当用户注册成功后,便可以在注册的手机号或者邮箱地址中收到一条应用的欢迎短信或者欢迎邮件.以便让开发者更快地 ...

  10. 通过实现仿照FeignClient框架原理的示例来看清FeignClient的本质

    前言 FeignClient的实现原理网上一搜一大把,此处我就不详细再说明,比如:Feign原理 (图解) - 疯狂创客圈 - 博客园 (cnblogs.com),而且关于FeignClient的使用 ...