CF 576D Flights for Regular Customers【矩阵快速幂】【图论】
正解:
将边按照d值的大小排序,从小到大依次枚举解锁当前边的时间情况。
使用三个矩阵:
其中a,b可以用bitset代替。f每一次用Floyd更新。
当枚举到一条边时,距离解锁该边还要走步,我们就考虑在这几步中,他可以到达那些节点。以此更新b。
每走一步,a就要乘上自己一次,更新路径数量,再把a的幂与b相乘,这样更新b矩阵,注意这里a不会变,我们只使用它的值来乘方,乘方后的矩阵就是所有的走的情况。
然后使用Floyd更新新加入的边对于路径长度的影响。
最后记录当前的,再更新a。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m;
struct node{
int u,v,d;
bool operator < (const node &b){
return d<b.d;
}
}p[160];
const int N=160;
bitset<N> a[N],b[N];
int f[N][N];
void Mul(bitset<N> *a,bitset<N> *b){
bitset<N> ret[N];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]){
ret[i]|=b[j];
}
}
}
for(int i=1;i<=n;i++){
a[i]=ret[i];
}
return ;
}
void Pow(bitset<N> *a,int b){
bitset<N> ret[N];
for(int i=1;i<=n;i++){
ret[i][i]=1;
}
while(b!=0){
if(b&1){
Mul(ret,a);
}
Mul(a,a);
b>>=1;
}
for(int i=1;i<=n;i++){
a[i]=ret[i];
}
return ;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>p[i].u>>p[i].v>>p[i].d;
}
sort(p+1,p+m+1);
memset(f,inf,sizeof f);
for(int i=1;i<=n;i++){//路径长度
f[i][i]=0;
}
int cnt=0;
int ans=inf;
for(int i=1;i<=n;i++){
b[i][i]=1;//自己可以到达自己
}
for(int i=1;i<=m;i++){
int x=p[i].u,y=p[i].v,d=p[i].d;
int delta=d-cnt;//$\Delta d$
bitset<N> tmp[N];
for(int i=1;i<=n;i++){
tmp[i]=a[i];
}
Pow(tmp,delta);//快速幂
Mul(b,tmp);
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
f[j][k]=min(f[j][k],f[j][x]+1+f[y][k]);//更新路径长度
}
}
for(int j=1;j<n;j++){
if(b[1][j]){
ans=min(ans,d+f[j][n]);//更新答案
}
}
a[x][y]=1;//更新a
cnt=d;
}
cout<<ans<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】