1344:【例4-4】最小花费
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 4204 通过数: 1843
【题目描述】
在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。
【输入】
第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。
以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。
最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。
【输出】
输出A使得B到账100元最少需要的总费用。精确到小数点后8位。
【输入样例】
3 3
1 2 1
2 3 2
1 3 3
1 3
【输出样例】
103.07153164
【提示】
【数据规模】
1≤n≤2000
思路:
Dijkstra
(1)a [ i ] [ j ] 存转账率
(2)dis [ i ] 是 a [ 起点 ] [ i ]
(3)f [ i ] 判断是否已经尝试过
(4)前驱结点 k
所求的结果 :ans * a[x][y]=100 即 ans=100 / a[x][y]
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 2001
using namespace std;
double a[N][N],dis[N],minn;
int f[N],n,m,k,x,y;
void read(){
int xx,yy,zz;
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++)
{
scanf("%d%d",&xx,&yy);
scanf("%lf",&a[xx][yy]);
a[xx][yy] = (100 - a[xx][yy])/100;
a[yy][xx] = a[xx][yy];
}
cin >> x >> y;
}
void dijkstra(int x){//dijkstra 算法
for(int i = 1; i <= n; i++)
dis[i] = a[x][i];
dis[x] = 1;
f[x] = 1;
for(int i = 1; i <= n-1;i++)
{
minn = 0;
for(int j = 1; j <= n; j++)
if(!f[j] && dis[j] > minn)
{
k = j;
minn = dis[j];
}
f[k] = 1;
if(k == y) break;
for(int j = 1; j <= n; j++)
if(!f[j] && dis[k]*a[k][j] > dis[j])
dis[j] = dis[k] * a[k][j];
}
}
int main(){
read();
dijkstra(x);
printf("%.8lf",100/dis[y]);//ans * a[x][y]=100 即 ans=100 / a[x][y]
return 0;
}