最小花费

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;
 }

猜你喜欢

转载自www.cnblogs.com/tingtin/p/11405310.html