题意:

给一个\(n\)点\(m\)边的连通图 每个边有一个权值\(d\) 当且仅当当前走过的步数\(\ge d\)时 才可以走这条边 问从节点\(1\)到节点\(n\)的最短路

好神的一道题 直接写做法喽

首先我们对边按\(d_i\)由小到大排序 设\(f_i\)表示加上\(1\sim i-1\)的所有边走\(d_i\)次后各点间的联通情况 \(G\)表示只连\(1\sim i-1\)的边的邻接矩阵 这些我们可以用一个\(01\)邻接矩阵来存储 则有

\(f_i=f_{i-1}*G^{d_i-d_{i-1}}\)

这很明显是一个矩阵快速幂的过程

之后只需要判断\(1\)与\(n\)之间是否联通 不连通就连下一条边继续判断 否则在当前的范围内二分判断

这样的复杂度还是不够优 我们发现矩阵相乘的过程可以压位后来做 于是将一个矩阵的状态压成\(n\)个\(bitset<n>\) 这样就可过了

我的代码没有压位 而是直接暴力相乘 不过做了点小优化居然就过了~

#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi fisrt
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=155;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
int x=0,rev=0,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return rev?-x:x;
}
struct data{
int u,v,t;
bool operator < (const data&ch){
return t<ch.t;
}
}e[N];
int cnt,n,m,tmp[N],sz,bin[32]={1};
struct matrix{
bool v[N][N];
matrix operator * (const matrix&b){
matrix c;cl(c.v);
for(int j=1;j<=n;j++)
for(int i=1;i<=n;i++){
if(!v[j][i]) continue;
for(int k=1;k<=n;k++)
c.v[j][k]|=v[j][i]&&b.v[i][k];
}
return c;
}
}g[N],G,f[N][32];
bool judge(int x){
int pos=upper_bound(tmp+1,tmp+sz+1,x)-tmp-1,ret=x-tmp[pos];
// debug("x=%d pos=%d\n",x,pos);
matrix d=g[pos];
// bug(d.v[1][n]);
for(int k=0;k<=30;k++){
if(bin[k]&ret){
d=d*f[pos][k];
}
}
return d.v[1][n];
}
int main(){
#ifdef Devil_Gary
freopen("in.txt","r",stdin);
#endif
n=read(),m=read();
for(int i=1;i<=30;i++) bin[i]=bin[i-1]<<1;
for(int i=1;i<=n;i++) g[1].v[i][i]=1;
for(int i=1;i<=m;i++){
e[++cnt].u=read(),e[cnt].v=read(),e[i].t=read();
// if(!e[i].t) g[1].v[e[i].u][e[i].v]=1;
tmp[++sz]=e[i].t;
}
e[++cnt].u=n,e[cnt].v=n,e[cnt].t=0,tmp[++sz]=0;
sort(tmp+1,tmp+sz+1);
sz=unique(tmp+1,tmp+sz+1)-tmp-1;
sort(e+1,e+cnt+1);
for(int i=1,j=1;i<=sz;i++){
for(;e[j].t<=tmp[i]&&j<=cnt;j++){
G.v[e[j].u][e[j].v]=1;
}
f[i][0]=G;
for(int k=1;k<=30;k++) f[i][k]=f[i][k-1]*f[i][k-1];
if(i==sz) continue;
int ret=tmp[i+1]-tmp[i];
g[i+1]=g[i];
for(int k=0;k<=30;k++){
if(bin[k]&ret){
g[i+1]=g[i+1]*f[i][k];
}
}
}
int l=0,r=1e9+155;
while(l<r){
int mid=l+r>>1;
if(judge(mid)) r=mid;
else l=mid+1;
}
/* debug("l=%d rr=%d\n",l,tmp[sz]+n+1);*/
if(l==1e9+155) return puts("Impossible"),0;
return !printf("%d\n",l);
}

下面这份是压位的做法 我直接粘来的

#include <bits/stdc++.h>
using namespace std;
int n, m;
const int N = 160;
struct edge
{
int a, b, c;
} E[N];
struct mat
{
bitset <N> d[N];
} O, I, P, Q;
int comp(edge x, edge y)
{
return x.c < y.c;
}
mat operator * (mat a, mat b)
{
mat c;
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= n; ++ j)
if (a.d[i][j])
c.d[i] |= b.d[j];
return c;
}
mat operator ^ (mat a, int b)
{
mat c = I;
for (; b; b >>= 1, a = a * a)
if (b & 1) c = c * a;
return c;
}
void print(mat a)
{
for (int i = 1; i <= n; ++ i)
{
for (int j = 1; j <= n; ++ j)
cerr << a.d[i][j] << " ";
cerr << endl;
}
}
int res;
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++ i)
I.d[i][i] = 1;
for (int i = 1; i <= m; ++ i)
cin >> E[i].a >> E[i].b >> E[i].c;
sort(E + 1, E + m + 1, comp);
E[m + 1].c = E[m].c + n + 5;
P = I; Q.d[n][n] = 1;
for (int i = 1; i <= m + 1; ++ i)
{
cout<<i<<endl;
mat tmp = P * (Q ^ (E[i].c - E[i - 1].c));
if (!tmp.d[1][n])
{
Q.d[E[i].a][E[i].b] = 1;
P = tmp;
continue;
}
res = E[i - 1].c;
while (!P.d[1][n]) P = P * Q, res ++;
cout << res << endl;
return 0;
}
cout << "Impossible" << endl;
}

Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP的更多相关文章

  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(bitset 优化广义矩阵乘法)

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

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

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

  5. Codeforces 989E A Trance of Nightfall 矩阵快速幂+DP

    题意:二维平面上右一点集$S$,共$n$个元素,开始位于平面上任意点$P$,$P$不一定属于$S$,每次操作为选一条至少包含$S$中两个元素和当前位置$P$的直线,每条直线选取概率相同,同一直线上每个 ...

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

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

  7. (中等) 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 ...

  8. Codeforces Round #536 (Div. 2) F 矩阵快速幂 + bsgs(新坑) + exgcd(新坑) + 欧拉降幂

    https://codeforces.com/contest/1106/problem/F 题意 数列公式为\(f_i=(f^{b_1}_{i-1}*f^{b_2}_{i-2}*...*f^{b_k} ...

  9. codeforces 691E 矩阵快速幂+dp

    传送门:https://codeforces.com/contest/691/problem/E 题意:给定长度为n的序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二 ...

随机推荐

  1. Spark记录-Scala异常与处理

    Scala try-catch语句 Scala提供try和catch块来处理异常.try块用于包含可疑代码.catch块用于处理try块中发生的异常.可以根据需要在程序中有任意数量的try...cat ...

  2. 原生JS 基础总结

    0. 好习惯 分号 ; 花括号 {}, var 弄清楚 null , undefined 区别 , isNaN, === 与 == 区别 1. prompt , confirm , alert 不同框 ...

  3. ASP.NET私有构造函数作用

    一.私有构造函数的特性 1.一般构造函数不是私有或者保护成员,但构造函数可以使私有成员函数,在一些特殊的场合,会把构造函数定义为私有或者保护成员. 2.私有构造函数是一种特殊的实例构造函数.它通常用在 ...

  4. codeforces 235 div2 B. Sereja and Contests

    Sereja is a coder and he likes to take part in Codesorfes rounds. However, Uzhland doesn't have good ...

  5. 第10月第20天 afnetwork like MKNetworkEngine http post

    1. + (AFHTTPRequestOperation *)requestSellerWithCompletion:(requestFinishedCompletionBlock)successBl ...

  6. EM算法理解

    一.概述 概率模型有时既含有观测变量,又含有隐变量,如果概率模型的变量都是观测变量,那么给定数据,可以直接利用极大似然估计法或者贝叶斯估计法估计模型参数.但是,当模型同时又含有隐变量时,就不能简单地使 ...

  7. spring事务详解(二)实例

    在Spring中,事务有两种实现方式: 编程式事务管理: 编程式事务管理使用底层源码可实现更细粒度的事务控制.spring推荐使用TransactionTemplate,典型的模板模式. 申明式事务管 ...

  8. 如何对xilinx FPGA进行bit文件加密

    记录背景:最近在用Vivado评估国外一个公司所提供的ISE所建的工程时,由于我并没有安装ISE工程,因此将其提供的所有v文件导入到Vivado中,对其进行编译.添加完之后成功建立顶层文件,但奇怪的是 ...

  9. nc用法【转】

    linux nc命令使用详解 功能说明:功能强大的网络工具 语 法:nc [-hlnruz][-g<网关...>][-G<指向器数目>][-i<延迟秒数>][-o& ...

  10. 高可用的MongoDB集群【转】

    刚接触MongoDB,就要用到它的集群,只能硬着头皮短时间去看文档和尝试自行搭建.迁移历史数据更是让人恼火,近100G的数据文件,导入.清理垃圾数据执行的速度蜗牛一样的慢.趁着这个时间,把这几天关于M ...