最小花费
1111: 最小花费 时间限制: 1 Sec 内存限制: 128 MB 提交: 95 解决: 12 [提交] [状态] [讨论版] [命题人:test] 题目描述 在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。 输入 输入包含多组测试用例。 对于每组样例,第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。(0<n<=2000)以下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
#include <bits/stdc++.h> using namespace std; #define ll long long #define N 2100 #define inf 100000000 int n,m; int g[N][N],d[N],pre[N]; int num[N]; bool vis[N]; int st,ed; void init() { for(int i =0;i<N;i++) { for(int j =0;j<N;j++) { if(i==j) g[i][j] =0; else g[i][j] = inf; } vis[i] = 0;d[i] =inf;pre[i] =-1; num[i] = 0; } } int x,y,z; void dijk(int st){ d[st] =0;num[st] =1; int min_num,minn; for(int i =0;i<n-1;i++) { minn=inf; for(int j =1;j<=n;j++){ if(!vis[j]&&d[j]<minn){ minn=d[j]; min_num=j; } } vis[min_num] =1; for(int k =1;k<=n;k++){ if(!vis[k]){ if(d[k]>d[min_num]+g[min_num][k]){ d[k]=d[min_num]+g[min_num][k]; pre[k] =min_num; num[k] =num[min_num]+1; } else if(d[k]==d[min_num]+g[min_num][k]){ if(num[k]<num[min_num]+1){//肯定是在相同路径长度下,走的路径边数越多越优 num[k] =num[min_num]+1; pre[k] =min_num; } } } } } } x*(1-z1%)(1-z2%)...==100 x=100/(1-z1%)(1-z2%)...//分母要最大,求最短路径 //相同路径长度下,走的路径边数越多越优 int main() { while(~scanf("%d%d",&n,&m)) { init(); for(int i =0;i<m;i++){ scanf("%d%d%d",&x,&y,&z); g[x][y]=g[y][x]=z; } scanf("%d%d",&st,&ed); dijk(st); double ret= 100.0; for(int j =ed;pre[j]!=-1;j=pre[j]) { //printf("%d ",j); double x = g[j][pre[j]]*1.0; //cout<<x<<endl; ret/=(1-x*0.01); //cout<<ret<<endl; } printf("%.8f\n",ret); } return 0; }