[洛谷P1576] 最小花费
Description
在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。
第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。
以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。
最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。
输出A使得B到账100元最少需要的总费用。精确到小数点后8位。
Solution
dijkstra+堆优化
最小花费就是把每个人都看作一个点,每次转账看作一条边,花费看作边权
最后呢要处理一下 因为要输出钱 而不是汇率
AC code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #define pa pair<double, int> 6 using namespace std; 7 //priority_queue<pa, vector<pa>, greater<pa> >q; 8 priority_queue<pa>q; 9 struct emmm { 10 int next, to; 11 double dis; 12 }e[200010]; 13 int n, m, num, head[200010], ss, ee, vis[20010]; 14 double dis[200010]; 15 void add(int from, int to, double dis) { 16 e[++num].next = head[from]; 17 e[num].to = to; 18 e[num].dis = dis; 19 head[from] = num; 20 } 21 void dijkstra() { 22 memset(dis, -0x3f, sizeof(dis)); 23 dis[ss] = 1; 24 q.push(make_pair(1, ss)); 25 while (!q.empty()) { 26 int now = q.top().second; 27 q.pop(); 28 if (vis[now]) continue; 29 vis[now] = 1; 30 for (int i = head[now]; i; i = e[i].next) { 31 int v = e[i].to; 32 33 if (dis[v] < dis[now] * e[i].dis) { 34 dis[v] = dis[now] * e[i].dis; 35 q.push(make_pair(dis[v], v)); 36 } 37 } 38 } 39 } 40 int main() { 41 ios::sync_with_stdio(0); 42 cin >> n >> m; 43 for (int i = 1;i <= m; i++) { 44 int x, y; 45 double z; 46 cin >> x >> y >> z; 47 add(y, x, 1.0-(double)(z/100)); 48 add(x, y, 1.0-(double)(z/100)); 49 } 50 cin >> ss >> ee; 51 dijkstra(); 52 printf("%.8lf\n",100 / dis[ee]); 53 return 0; 54 }