1. 程式人生 > 其它 >一道神奇的最短路題(對數的用法)

一道神奇的最短路題(對數的用法)

給出一張無向帶權圖,找一條從s到t的路徑使經過的邊權值乘積最小。

N,M<=1e5 weight<=1e4

直接dij的話len會達到1e4^1e5。

但是如果將邊權向這樣取個對數

VP = weightP1 × weightP2 × ... × weightPK

ln VP = ln weightP1 + ln weightP2 + ... + ln weightPK

就可以直接跑dij了

#include<bits/stdc++.h>
using namespace std;
const int MM=200005;
long long n,m,u,v,ans[MM],vis[MM],to[MM],nxt[MM],head[MM],f[MM],s,t,tot,tmp,_min;;
double q[MM],len[MM],w,W; void dij() { while(!vis[t]) { double tmp=100000;int _min; for(int i=1;i<=n;i++) if(!vis[i]&&len[i]<tmp) tmp=len[i],_min=i; vis[_min]=1; for(int i=head[_min];i;i=nxt[i]) if(len[_min]+q[i]<=len[to[i]]) len[to[i]]
=len[_min]+q[i],f[to[i]]=_min; } } void find(int now) { ans[++tot]=now; if(now==s) return; find(f[now]); } void pp() { find(t); for(int i=tot;i>=1;i--) cout<<ans[i]<<' '; } void add(int u,int v,int w) { W=log10(w); nxt[++tot]=head[u]; head[u]
=tot; to[tot]=v; q[tot]=W; } int main() { //freopen("multi.in","r",stdin); //freopen("nulti.out","w",stdout); memset(len,0x42,sizeof(len)); cin>>n>>m; for(int i=1;i<=n;i++) cin>>u>>v>>w,add(u,v,w),add(v,u,w); tot=0; cin>>s>>t; len[s]=1; dij(); pp(); return 0; }