SZY 的旅行 题解
将图按照邻接矩阵存为一个矩阵,则有性质为:该矩阵的 \(k\) 次方反映了 在该图上恰好走 \(k\) 次的可达性。
有了这条性质可以按边权将所有边排序,在图上动态加入能新走的边,用矩阵快速幂处理出当前图恰好走这条边边权次的可达性矩阵。每新加入一条边,用 floyd 求出加入这条边影响后新的最短路。
code:
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define debug cout<<"DEBUG"<<endl;
#define pb push_back
#define pii pair<int,int>
#define vi vector<int>
#define imp map<int,int>
using namespace std;
const int N=155;
int n,m;
ll ans=1e18,dis[N][N];
struct EDGE{
int from,to;
ll c;
}e[N];
struct Matrix{
bitset<N>a[N];
Matrix(){
for(int i=0;i<N;i++) a[i].reset();
}
void clear(){
for(int i=0;i<N;i++){
a[i].reset();
}
}
friend Matrix operator * (Matrix A,Matrix B){
Matrix ans;
ans.clear();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(A.a[i][j]) ans.a[i]|=B.a[j];
}
}
return ans;
}
}now,bas;
bool cmp(EDGE A,EDGE B){
return A.c<B.c;
}
Matrix qpow(Matrix x,int y){
Matrix prod;
prod.clear();
for(int i=1;i<=n;i++){
prod.a[i][i]=1;
}
while(y>0){
if(y&1) prod=prod*x;
y>>=1;
x=x*x;
}
return prod;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
e[i].from=x,e[i].to=y,e[i].c=z;
}
now.clear(),bas.clear();
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=n;i++){
dis[i][i]=0;
now.a[i][i]=1;
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
now=now*qpow(bas,e[i].c-e[i-1].c);
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
dis[j][k]=min(dis[j][k],dis[j][e[i].from]+dis[e[i].to][k]+1);
for(int j=1;j<=n;j++){
if(!now.a[1][j]) continue;
ans=min(ans,e[i].c+dis[j][n]);
}
bas.a[e[i].from][e[i].to]=1;
}
printf("%lld\n",ans);
return 0;
}
本文来自博客园,作者:Aurora_Borealis,转载请注明原文链接:https://www.cnblogs.com/Aurora-Borealis-Not-Found/p/17764421.html