(中等) 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 there is an airport is located.
Also, there is the only one airline, which makes m flights. Unfortunately, to use them, you need to be a regular customer of this company, namely, you have the opportunity to enjoy flight i from city ai to city bi only if you have already made at least di flights before that.
Please note that flight i flies exactly from city ai to city bi. It can not be used to fly from city bi to city ai. An interesting fact is that there may possibly be recreational flights with a beautiful view of the sky, which begin and end in the same city.
You need to get from city 1 to city n. Unfortunately, you've never traveled by plane before. What minimum number of flights you have to perform in order to get to city n?
Note that the same flight can be used multiple times.
题意大致就是给一个图,然后每条边有一个限制条件d表示至少已经走过d长度才能打开这条路,然后问最少需要多少步才能从1到n。
本来看到n的数据范围只有150时就应该想到矩阵的,然而忘记了。。。
邻接矩阵有一个性质就是他的k次幂的第 i 行 j 列就表示从 i 正好走 k 步到 j 的方案数。然后对于这题,对每条路排序,然后一次次对矩阵进行乘法,当次数到限制条件的时候就增加新的可以走的边,然后继续乘。。。
但是这样的复杂度就有点。。。了,矩阵快速幂的复杂度是n^3 log k的,然后是m次,所以复杂度(n^3mlogk)的,比较大。。。但是对于CF那样速度巨快的机子,写的好的话也是可以过的。。。
不过这里可以用位运算加速,因为主要考虑的是矩阵的01,而不是方案数,所以用bitset可以加速很多。。。
代码如下:
// ━━━━━━神兽出没━━━━━━
// ┏┓ ┏┓
// ┏┛┻━━━━━━━┛┻┓
// ┃ ┃
// ┃ ━ ┃
// ████━████ ┃
// ┃ ┃
// ┃ ┻ ┃
// ┃ ┃
// ┗━┓ ┏━┛
// ┃ ┃
// ┃ ┃
// ┃ ┗━━━┓
// ┃ ┣┓
// ┃ ┏┛
// ┗┓┓┏━━━━━┳┓┏┛
// ┃┫┫ ┃┫┫
// ┗┻┛ ┗┻┛
//
// ━━━━━━感觉萌萌哒━━━━━━ // Author : WhyWhy
// Created Time : 2015年09月30日 星期三 22时03分41秒
// File Name : 1_D.cpp #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h> #include <bitset> using namespace std; const int MaxN=; int N; struct Mat
{
bitset <MaxN> num[MaxN]; Mat operator * (const Mat & b) const
{
Mat ret;
for(int i=;i<=N;++i)
for(int j=;j<=N;++j)
if(num[i][j])
ret.num[i]|=b.num[j];
return ret;
}
}; int M; struct Edge
{
int u,v,d; bool operator < (const Edge & b) const
{
return d<b.d;
}
}; Edge E[MaxN];
Mat ans,map1; Mat _pow(Mat base,int n)
{
Mat ret;
for(int i=;i<=N;++i) ret.num[i][i]=; while(n)
{
if(n&) ret=ret*base;
base=base*base;
n>>=;
}
return ret;
} int getans(int R)
{
int L=,M;
Mat temp=ans*_pow(map1,R); if(temp.num[][N]==)
{
ans=temp;
return ;
} while(R>L)
{
M=(L+R)>>;
temp=ans*_pow(map1,M);
if(temp.num[][N]) R=M;
else L=M+;
}
return L;
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout); scanf("%d %d",&N,&M);
for(int i=;i<=M;++i)
scanf("%d %d %d",&E[i].u,&E[i].v,&E[i].d);
sort(E+,E+M+);
++M;
E[M].d=+;
E[M].u=E[M].v=; if(E[].d)
{
puts("Impossible");
return ;
} int t; map1.num[N][N]=;
for(int i=;i<=N;++i) ans.num[i][i]=; map1.num[E[].u][E[].v]=;
for(int i=;i<=M;++i)
if(E[i].d!=E[i-].d)
{
if(t=getans(E[i].d-E[i-].d))
{
printf("%d\n",E[i-].d+t);
return ;
}
map1.num[E[i].u][E[i].v]=;
}
else
map1.num[E[i].u][E[i].v]=; puts("Impossible"); return ;
}
(中等) CF 576D Flights for Regular Customers (#319 Div1 D题),矩阵快速幂。的更多相关文章
- Codeforces 576D - Flights for Regular Customers(bitset 优化广义矩阵乘法)
题面传送门 题意: 有一张 \(n\) 个点 \(m\) 条边的有向图,你初始在 \(1\) 号点,边上有边权 \(c_i\) 表示只有当你经过至少 \(c_i\) 条边的时候你才能经过第 \(i\) ...
- Codeforces 576D Flights for Regular Customers(矩阵加速DP)
题目链接 Flights for Regular Customers 首先按照$d$的大小升序排序 然后分成$m$个时刻,每条路径一次处理过来. $can[i][j]$表示当前时刻$i$能否走到$j ...
- Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP
题意: 给一个$n$点$m$边的连通图 每个边有一个权值$d$ 当且仅当当前走过的步数$\ge d$时 才可以走这条边 问从节点$1$到节点$n$的最短路 好神的一道题 直接写做法喽 首先我们对边按$ ...
- Codeforces 576D. Flights for Regular Customers(倍增floyd+bitset)
这破题调了我一天...错了一大堆细节T T 首先显然可以将边权先排序,然后逐个加进图中. 加进图后,倍增跑跑看能不能到达n,不能的话加新的边继续跑. 倍增的时候要预处理出h[i]表示转移矩阵的2^0~ ...
- Codeforces 576D Flights for Regular Customers (图论、矩阵乘法、Bitset)
题目链接 http://codeforces.com/contest/576/problem/D 题解 把边按\(t_i\)从小到大排序后枚举\(i\), 求出按前\((i-1)\)条边走\(t_i\ ...
- 576D Flights for Regular Customers
分析 https://www.cnblogs.com/onioncyc/p/8037056.html 写的好像有点问题 但是大致就是这个意思 代码很好理解 代码 #include<bits/st ...
- CF576D Flights for Regular Customers 矩阵乘法 + Bitset优化
%%%cxhscst2's blog Codeforces 576D Flights for Regular Customers(矩阵加速DP) 代码非常优美 + 简洁,学习到了 Code: #inc ...
- 【CodeForces】576 D. Flights for Regular Customers
[题目]D. Flights for Regular Customers [题意]给定n个点m条边的有向图,每条边有di表示在经过该边前必须先经过di条边,边可重复经过,求1到n的最小经过边数.n,m ...
- 「CF576D」 Flights for Regular Customers
「CF576D」 Flights for Regular Customers 对不起我又想网络流去了 你看这长得多像啊,走过至少多少条边就是流量下界,然后没上界 但是这个题求的最少走多少条边啊...完 ...
随机推荐
- php.ini与php-fpm.conf配置文件的区别
php-fpm.conf是PHP-FPM特有的配置文件 php.ini是所以php模式中必须的配置文件 两者的区别是,php-fpm.conf是PHP-FPM进程管理器的配置文件,php.ini是PH ...
- linux服务器之LVS、Nginx和HAProxy负载均衡器对比总结
LVS特点: 1.抗负载能力强,使用IP负载均衡技术,只做分发,所以LVS本身并没有多少流量产生: 2.稳定性.可靠性好,自身有完美的热备方案:(如:LVS+Keepalived) 3.应用范围比较广 ...
- JSP精华知识点总结
本文转自:http://blog.csdn.net/qy1387/article/details/8050239 JSP精华知识点总结 Servlet三个要素 1.必须继承自HttpServlet 2 ...
- 实现jsp页面显示用户登录信息,利用session保存。
这是后台代码 这是jsp代码,上面是声明,下面是获得值.
- java.sql.ResultSet技术(从数据库查询出的结果集里取列值)
里面有一个方法可以在查询的结果集里取出列值,同理,存储过程执行之后返回的结果集也是可以取到的. 如图: 然后再运用 java.util.Hashtable 技术.把取到的值放入(K,V)的V键值里,K ...
- 转 [分享一个SQL] 查会话阻塞关系,层次关系.
with ash as (select /*+ materialize*/* from DBA_HIST_ACTIVE_SESS_HISTORY where sample_time between ...
- mysql具体语句示例
建表:(not null ,auto_increment, unique , primary key) create database balfish;use balfish;create table ...
- java模式:模板模式的简单理解
1.模板模式就是用虚类作为基类将几个要执行差不多操作中相同的部分提取出来,不同的部分各自实现! 2.下面给出简单栗子: 我要进行的操作是将大象和狐狸放入冰箱,放入大象和狐狸有相同的步骤:开冰箱和关冰箱 ...
- Linux学习 -- 权限管理
1 ACL权限 1.1 简介与开启 1.1.1 ACL权限是什么 access control list 访问控制表 解决传统的(owner,group,others)身份不足的情况 可以设置 特定用 ...
- 屏幕的尺寸(厘米)、屏幕分辨率(像素)、PPI它们之间是什么关系
屏幕的尺寸(厘米).屏幕分辨率(像素).PPI它们之间是什么关系? 添加评论 分享 赞同2反对,不会显示你的姓名 知乎用户,数据ETL,UNITY3D 刘大侠.如果 赞同 以iphone4 为例,分辨 ...