D65 最短路 Dijkstra 算法 P1576 最小花费

D65 最短路 Dijkstra 算法 P1576 最小花费_哔哩哔哩_bilibili

 

P1576 最小花费 - 洛谷

在 n 个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问 A 最少需要多少钱使得转账后 B 收到 100 元。

思路

两个人之间实际的汇率是 $1-z \%$,我们将人看做点,汇率看做边权。

如果 $A$ 到 $B$ 的汇率是 $x$ ,$B$ 到 $C$ 的汇率是 $y$ ,那么 $A$ 到 $C$ 的汇率就是 $x*y$。

我们用 Dijkstra 算法 求汇率的最长路,把方程中的加改为乘。

答案就是汇率最大,费用最少。

相关板子:

D02【模板】最短路 Dijkstra 算法 P4779 单源最短路径 - 董晓 - 博客园

// 最短路 Dijkstra 算法 O(mlogn)
#include<bits/stdc++.h>
using namespace std;

const int N=2005;
int n,m,s,t;
vector<pair<double,int>> e[N];
int vis[N];
double d[N];

void dijkstra(){
  priority_queue<pair<double,int>> q; //大根堆
  q.emplace(d[s]=1,s);
  while(q.size()){
    int u=q.top().second; q.pop();
    if(vis[u]) continue; 
    vis[u]=1;
    for(auto [w,v]:e[u]){
      if(d[v]<d[u]*w) 
        q.emplace(d[v]=d[u]*w,v); //d[v]从s到v的最大汇率
    }
  }
}
int main(){
  cin>>n>>m;
  for(int i=0,x,y,z; i<m; i++){
    cin>>x>>y>>z;
    double p=(100.0-z)/100; //汇率
    e[x].emplace_back(p,y);
    e[y].emplace_back(p,x);
  }
  cin>>s>>t;
  dijkstra(); //计算汇率的最长路
  printf("%.8lf\n",100/d[t]); //汇率最大,费用最小
}

 

posted @ 2026-02-12 17:49  董晓  阅读(126)  评论(0)    收藏  举报