'commit'
This commit is contained in:
117
TangDou/AcWing_TiGao/T3/MiniPath/1126.md
Normal file
117
TangDou/AcWing_TiGao/T3/MiniPath/1126.md
Normal file
@@ -0,0 +1,117 @@
|
||||
## [$AcWing$ $1126$. 最小花费](https://www.acwing.com/problem/content/1128/)
|
||||
|
||||
### 一、题目描述
|
||||
在 $n$ 个人中,某些人的银行账号之间可以互相转账。
|
||||
|
||||
这些人之间转账的手续费各不相同。
|
||||
|
||||
给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问 $A$ 最少需要多少钱使得转账后 $B$ 收到 $100$ 元。
|
||||
|
||||
**输入格式**
|
||||
第一行输入两个正整数 $n,m$,分别表示总人数和可以互相转账的人的对数。
|
||||
|
||||
以下 $m$ 行每行输入三个正整数 $x,y,z$,表示标号为 $x$ 的人和标号为 $y$ 的人之间互相转账需要扣除 $z\%$ 的手续费 ( $z<100$ )。
|
||||
|
||||
最后一行输入两个正整数 $A,B$。
|
||||
|
||||
数据保证 $A$ 与 $B$ 之间可以直接或间接地转账。
|
||||
|
||||
**输出格式**
|
||||
输出 $A$ 使得 $B$ 到账 $100$ 元最少需要的总费用。
|
||||
|
||||
精确到小数点后 $8$ 位。
|
||||
|
||||
**数据范围**
|
||||
$1≤n≤2000,m≤10^5$
|
||||
|
||||
**输入样例**:
|
||||
```cpp {.line-numbers}
|
||||
3 3
|
||||
1 2 1
|
||||
2 3 2
|
||||
1 3 3
|
||||
1 3
|
||||
```
|
||||
|
||||
**输出样例**:
|
||||
```cpp {.line-numbers}
|
||||
103.07153164
|
||||
```
|
||||
|
||||
### 二、题目解析
|
||||
假设初始金钱为$N$,那么如果要在最后一个人的手里得到$100$元,可得公式:
|
||||
$$\large N∗(1−z_1\%)∗(1−z_2\%)∗…∗(1−z_n\%)=100$$
|
||||
|
||||
$\Rightarrow$
|
||||
$$\large N=\frac{100}{(1−z_1\%)∗(1−z_2\%)∗…∗(1−z_n\%)}$$
|
||||
|
||||
要想$N$尽可能小,那么就要让 **分母尽可能大** ,即求$(1−z_1\%)∗(1−z_2\%)∗…∗(1−z_n\%)$的最大值。
|
||||
|
||||
**注意**:
|
||||
| | 最小值 | 最大值 |
|
||||
| ------------ | ---------------------------------------------------- | ------------------------ |
|
||||
| **优先队列** | **小根堆** | **大根堆** |
|
||||
| **实现** | ` priority_queue<PII, vector<PII>, greater<PII>> q;` | `priority_queue<PDI> q;` |
|
||||
更新的时候用:$d[v] = d[u] * (1 - w[i]\%)$。
|
||||
|
||||
### 三、$Dijkstra$
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
const int N = 2010;
|
||||
const int M = 2e5 + 10;
|
||||
|
||||
typedef pair<double, int> PDI; // 堆中数值是浮点数,注意区别
|
||||
|
||||
int n, m;
|
||||
double dis[N];
|
||||
bool st[N];
|
||||
|
||||
int h[N], e[M], ne[M], idx;
|
||||
double w[M]; // 边权为浮点数,与一般的题目有区别
|
||||
void add(int a, int b, double c) {
|
||||
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
|
||||
}
|
||||
int S, T;
|
||||
void dijkstra() {
|
||||
priority_queue<PDI> q; // 大顶堆
|
||||
dis[S] = 1;
|
||||
q.push({1, S});
|
||||
|
||||
while (q.size()) {
|
||||
auto t = q.top();
|
||||
q.pop();
|
||||
int u = t.second;
|
||||
if (st[u]) continue;
|
||||
st[u] = true;
|
||||
|
||||
for (int i = h[u]; ~i; i = ne[i]) {
|
||||
int v = e[i];
|
||||
double a = 1 - w[i];
|
||||
if (dis[v] < dis[u] * a) {
|
||||
dis[v] = dis[u] * a;
|
||||
q.push({dis[v], v});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
memset(h, -1, sizeof h);
|
||||
cin >> n >> m;
|
||||
|
||||
while (m--) {
|
||||
int a, b, c;
|
||||
cin >> a >> b >> c;
|
||||
double w = c * 0.01;
|
||||
add(a, b, w), add(b, a, w);
|
||||
}
|
||||
|
||||
cin >> S >> T;
|
||||
|
||||
dijkstra();
|
||||
printf("%.8lf\n", 100 / dis[T]);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user