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