【CodeForces】576 D. Flights for Regular Customers
【题目】D. Flights for Regular Customers
【题意】给定n个点m条边的有向图,每条边有di表示在经过该边前必须先经过di条边,边可重复经过,求1到n的最小经过边数。n,m<=150,di<=10^9,time=4s。
【算法】floyd+矩阵快速幂
【题解】需要计算步数,很容易联想到将floyd中每一步拆成矩阵乘法的经典做法。
令a[d][i][j]表示恰好d步能否从 i 走到 j(邻接矩阵) ,令b[d][i][j]表示当前已走d步时允许通过的边(连边矩阵)。
当前d步时,走一步相当于a[d+1][i][j]=max(a[d][i][k]&&b[d][k][j]),k=1~n(取max 是 或运算),将其定义为一次矩阵乘法就可以用矩阵快速幂优化了。
根据d的不同,连边矩阵b会发生至多m次变化。所以将所有边按d排序后顺序处理,每次快速幂的幂为d[i]-d[i-1],就能处理出走恰好d步能到达的点(作为起点集)。
最后,每次用1~i的所有边跑一次朴素的最短路(可以用floyd),从起点集到n的最短路+d就是每次的答案,取最小答案。
因为矩阵快速幂中使用的均为01矩阵,所以可以用bitset优化,从而满足时间限制。
复杂度O(m*n^3*log(di)/32+m*n^3),其中第二部分的最短路还可以用dijkstra算法优化,但已经不必要了。
#include<cstdio>
#include<cstring>
#include<bitset>
#include<algorithm>
using namespace std;
const int N=,inf=0x3f3f3f3f;
struct cyc{int x,y,d;}e[N];
int n,m,mp[N][N];
bitset<N>a[N],ans[N],c[N],z[N];
bool cmp(cyc a,cyc b){return a.d<b.d;}
void mul(bitset<N>a[N],bitset<N>b[N]){
for(int i=;i<=n;i++)c[i].reset();
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
if(a[i][k])c[i]|=b[k];
for(int i=;i<=n;i++)a[i]=c[i];
}
int main(){
scanf("%d %d",&n,&m);
for(int i=;i<=m;i++)scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].d);
sort(e+,e+m+,cmp);
for(int i=;i<=n;i++)ans[i].reset();
for(int i=;i<=n;i++)ans[i][i]=;
int ANS=inf;
for(int b=;b<=m;b++){
for(int i=;i<=n;i++)a[i].reset();
for(int i=;i<b;i++)a[e[i].x][e[i].y]=;
int k=e[b].d-e[b-].d;
while(k){
if(k&)mul(ans,a);
mul(a,a);
k>>=;
}
memset(mp,0x3f,sizeof(mp));
for(int i=;i<=n;i++)mp[i][i]=;
for(int j=;j<=b;j++)mp[e[j].x][e[j].y]=;
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
for(int i=;i<=n;i++)if(ans[][i])ANS=min(ANS,e[b].d+mp[i][n]);
}
if(ANS==inf)printf("Impossible");else printf("%d",ANS);
return ;
}
代码中要注意的是,因为这里矩阵乘法并不是通常意义上定义的,所以初始值的设置不能沿袭“单位矩阵”等概念,而必须考虑其实际意义。
初始邻接矩阵:全为0,对角线为1,表示初始只能到达自己。(第二轮后可能就不能到达自己了)
连边矩阵:对角线为0,表示不能通过连边到达自己,这样才能使邻接矩阵表示恰好d步的可达信息。
如果连边矩阵的对角线1,即能到达自己,那么表示的就是<=d步的可达信息。
【CodeForces】576 D. Flights for Regular Customers的更多相关文章
- 【CodeForces】576 B. Invariance of Tree
[题目]B. Invariance of Tree [题意]给定n个数的置换,要求使n个点连成1棵树,满足u,v有边当且仅当a[u],a[v]有边,求一种方案或无解.n<=10^5. [算法]数 ...
- 【CodeForces】576 C. Points on Plane
[题目]C. Points on Plane [题意]给定坐标系中n个点的坐标(范围[0,10^6]),求一种 [ 连边形成链后总长度<=2.5*10^9 ] 的方案.n<=10^6. [ ...
- 【Codeforces】CF 5 C Longest Regular Bracket Sequence(dp)
题目 传送门:QWQ 分析 洛谷题解里有一位大佬讲的很好. 就是先用栈预处理出可以匹配的左右括号在数组中设为1 其他为0 最后求一下最长连续1的数量. 代码 #include <bits/std ...
- 【Codeforces】Round #491 (Div. 2) 总结
[Codeforces]Round #491 (Div. 2) 总结 这次尴尬了,D题fst,E没有做出来.... 不过还好,rating只掉了30,总体来说比较不稳,下次加油 A:If at fir ...
- 【Codeforces】Round #488 (Div. 2) 总结
[Codeforces]Round #488 (Div. 2) 总结 比较僵硬的一场,还是手速不够,但是作为正式成为竞赛生的第一场比赛还是比较圆满的,起码没有FST,A掉ABCD,总排82,怒涨rat ...
- Codeforces 576D Flights for Regular Customers(矩阵加速DP)
题目链接 Flights for Regular Customers 首先按照$d$的大小升序排序 然后分成$m$个时刻,每条路径一次处理过来. $can[i][j]$表示当前时刻$i$能否走到$j ...
- CF576D Flights for Regular Customers 矩阵乘法 + Bitset优化
%%%cxhscst2's blog Codeforces 576D Flights for Regular Customers(矩阵加速DP) 代码非常优美 + 简洁,学习到了 Code: #inc ...
- 「CF576D」 Flights for Regular Customers
「CF576D」 Flights for Regular Customers 对不起我又想网络流去了 你看这长得多像啊,走过至少多少条边就是流量下界,然后没上界 但是这个题求的最少走多少条边啊...完 ...
- 【CodeForces】601 D. Acyclic Organic Compounds
[题目]D. Acyclic Organic Compounds [题意]给定一棵带点权树,每个点有一个字符,定义一个结点的字符串数为往下延伸能得到的不重复字符串数,求min(点权+字符串数),n&l ...
随机推荐
- C++ Primer Plus学习:第一章
C++入门第一章:预备知识 C++简介 C++融合了三种不同的编程方式: C语言代表的过程性语言. C++在C语言基础上添加的类代表的面向对象语言. C++模板支持的泛型编程. C++简史 20世纪7 ...
- 3dContactPointAnnotationTool开发日志(二七)
今天的主要工作是把选中物体以及复制删除物体和右边三个面板联系起来,就是通过鼠标框选住物体,右边面板的对应项的颜色也会改变,而且通过右边面板也能控制物体的选中状态,被选中的物体成cyan青色,并且包 ...
- Qt多线程-QtConcurrent并行运算高级API
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QtConcurrent并行运算高级API 本文地址:http://tec ...
- 【转】Base64算法详解
原文链接:https://blog.csdn.net/robertcpp/article/details/51628647 完整的BASE64定义可见RFC 1421和RFC 2045.编码后的数据比 ...
- NIO网络编程中重复触发读(写)事件
一.前言 公司最近要基于Netty构建一个TCP通讯框架, 因Netty是基于NIO的,为了更好的学习和使用Netty,特意去翻了之前记录的NIO的资料,以及重新实现了一遍NIO的网络通讯,不试不知道 ...
- BZOJ4985 评分(二分答案+树形dp)
首先二分答案简化一下问题,现在只有0和1了,要求最后剩下的是1.再简化一下考虑没有已固定的位置怎么做.考虑每个位置由其合并到的位置连边,显然这样形成了一棵三叉树.设f[i]为使得某位置为1其子树至少要 ...
- Redis Scan迭代器遍历操作原理(一)
Redis在2.8.0版本新增了众望所归的scan操作,从此再也不用担心敲入了keys*, 然后举起双手看着键盘等待漫长的系统卡死了··· 命令的官方介绍在这里, 中文版由huangz同学细心翻译了, ...
- CSS3制作3D水晶糖果按钮
本人仿照20个漂亮 CSS3 按钮效果及优秀的制作教程中的BonBon(Candy)Button实现了其棒棒糖果按钮,如下图所示: 在线演示地址见here. 使用完全使用CSS实现,无需JS.源码如下 ...
- 电子商务(电销)平台中内容模块(Content)数据库设计明细
以下是自己在电子商务系统设计中的数据库设计经验总结,而今发表出来一起分享,如有不当,欢迎跟帖讨论~ 文章表 (article)|-- 自动编号|-- 文章标题 (title)|-- 文章类别编号 (c ...
- Virtual Box虚拟机下CentOS网络设置
VirtualBox中有4中网络连接方式: a. NAT 网络地址转换模式(Network Address Translation)b. Bridge ...