[洛谷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

 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 }
AC Code

 

posted @ 2019-08-15 10:43  _sheldon  阅读(358)  评论(0编辑  收藏  举报