题解:P11898 移动迷宫
题目传送门:P11898 移动迷宫。
思路
首先一个原始长度为
根据上面的推导我们发现每一条边的长度在
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=754974721,N=1e5+10;
int d[N][4],n,m;
#define pii pair<int,int>
vector<pii >a[N];
map<pii,int>vis;
inline int read(){
char c=getchar();
int f=1,ans=0;
while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
return ans*f;
}
void exgcd(int a,int b,int &x,int &y){
if (b==0) x=1,y=0;
else exgcd(b,a%b,y,x),y-=a/b*x;
}
inline int inv(int a){
int x,y;
exgcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
inline int get(int t,int op){
if (op==1) return t;
else if (op==2) return inv(1-t+mod);
return (t-1+mod)*inv(t)%mod;
}
struct nord{
int u,w,op;
bool operator <(const nord &x) const{
return w>x.w;
}
};
main(){
n=read(),m=read();
while(m--){
int u=read(),v=read(),w=read();
a[u].push_back({v,w});
a[v].push_back({u,w});
}
for (int i=1;i<=n;i++) d[i][1]=d[i][2]=d[i][3]=1e17;
d[1][3]=0;
priority_queue<nord>q;
q.push({1,0,3});
while(!q.empty()){
nord x=q.top();q.pop();
int u=x.u,op=x.op;
if (vis.count({u,op})) continue;
vis[{u,op}]=1;
for (auto i:a[u]){
int v=i.first;
int x=op+1;
if (x==4) x=1;
int w=get(i.second,x);
if (d[v][x]>d[u][op]+w){
d[v][x]=d[u][op]+w;
q.push({v,d[v][x],x});
}
}
}
cout <<min(min(d[n][1],d[n][2]),d[n][3]);
return 0;
}