P1576 最小花费

题目描述

在$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-z$表示汇率,剩下就是套SPFA板子

代码

#include <bits/stdc++.h>

#define Enter puts("")
#define Space putchar(' ')
#define MAXN 1000010

using namespace std;

typedef long long ll;
typedef double Db;

inline ll Read()
{
    ll Ans = 0;
    char Ch = getchar() , Las = ' ';
    while(!isdigit(Ch))
    {
        Las = Ch;
        Ch = getchar();
    }
    while(isdigit(Ch))
    {
        Ans = (Ans << 3) + (Ans << 1) + Ch - '0';
        Ch = getchar();
    }
    if(Las == '-')
        Ans = -Ans;
    return Ans;
}

inline void Write(ll x)
{
    if(x < 0)
    {
        x = -x;
        putchar('-');
    }
    if(x >= 10)
        Write(x / 10);
    putchar(x % 10 + '0');
}

int Count , Head[MAXN];
Db Dis[MAXN];
bool Visit[MAXN];
int Start , End;
int m , n;

struct Edge
{
    int To , Next;
    Db Dis;
}E[MAXN];

inline void Add_Edge(int u , int v , Db d)
{
    E[++Count].Dis = 1 - d;
    E[Count].To = v;
    E[Count].Next = Head[u];
    Head[u] = Count;
}

queue <int> Q;

inline void SPFA()
{
    memset(Visit , false , sizeof(Visit));
    memset(Dis , 0 , sizeof(Dis));
    Q.push(Start);
    Dis[Start] = 1;
    Visit[Start] = true;
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        Visit[u] = false;
        for(int i = Head[u]; i; i = E[i].Next)
        {
            int v = E[i].To;
            if(Dis[v] < E[i].Dis * Dis[u])
            {
                Dis[v] = Dis[u] * E[i].Dis;
                if(!Visit[v])
                {
                    Q.push(v);
                    Visit[v] = true;
                }
            }
        }
    }
}

int main()
{
    n = Read() , m = Read();
    for(int i = 1; i <= m; i++)
    {
        int u = Read() , v = Read() , d = Read();
        Add_Edge(u , v , (Db) d / 100);
        Add_Edge(v , u , (Db) d / 100);
    }
    Start = Read() , End = Read();
    SPFA();
    //printf("%.8lf" , Dis[End]);
    printf("%.8lf" , 100 / Dis[End]);
    return 0;
}

 

posted @ 2021-05-21 18:22  Tenderfoot  阅读(179)  评论(0编辑  收藏  举报