题意:

给一个\(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. bzoj千题计划247:bzoj4903: [Ctsc2017]吉夫特

    http://uoj.ac/problem/300 预备知识: C(n,m)是奇数的充要条件是 n&m==m 由卢卡斯定理可以推出 选出的任意相邻两个数a,b 的组合数计算C(a,b)必须是奇 ...

  2. [转载]嵌入式C语言中的Doxygen注释模板

    http://blog.csdn.net/willerency/article/details/7083953 嵌入式C语言开发中通常使用Doxygen进行文档的生成.Doxygen支持多种格式,非常 ...

  3. 【译】SQLskills SQL101:Trace Flags、ERRORLOG、Update Statistics

    最近阅读SQLskills SQL101,将Erin Stellato部分稍作整理.仅提取自己感兴趣的知识点,详细内容请阅读原文. 一.Trace Flags推荐开启三个跟踪标记1118.3023.3 ...

  4. 数链剖分(Housewife Wind )

     题目链接:https://vjudge.net/contest/279350#problem/B 题目大意:给你n,q,s.n指的是有n个点,q代表有q次询问,s代表的是起点.然后接下来会有n-1条 ...

  5. sonar Lint ----code bad smell

    类名注释报黄: 去掉这段黄做法:alt+enter 本文参考: http://www.cnblogs.com/xxoome/p/6677170.html

  6. shell升级

    对/sbin/nologin的理解   系统账号的shell使用 /sbin/nologin ,此时无法登陆系统,即使给了密码也不行.   所谓“无法登陆”指的仅是这个用户无法使用bash或其他she ...

  7. python爬虫-基础

    所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地. 类似于使用程序模拟IE浏览器的功能,把URL作为HTTP请求的内容发送到服务器端, 然后读取服务器端的响应资源. 1.浏 ...

  8. 解决MySQL忘记root密码

    网上有很多关于忘记MySQL root密码的一些文章,里面都有写怎么去解决,但有时觉得写得太恶心,要么一字不漏的抄别人的,要么就说得不清不楚,好了,不吐槽了,以下是解决的整个过程. 首先我们要知道忘记 ...

  9. SQL Server 2

    一.创建数据表 1.连接服务器: 2.右击“表”节点,选择“新建表”,即: 3.在弹出的“表设计器”中,输入表的列名.选择的数据类型及是否允许为空,即: 二.导入数据表 1.右击表名,弹出菜单,选择“ ...

  10. react + redux 完整的项目,同时写一下个人感悟

    先附上项目源码地址和原文章地址:https://github.com/bailicangd... 做React需要会什么? react的功能其实很单一,主要负责渲染的功能,现有的框架,比如angula ...