题意分析
在 n 个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问 A 最少需要多少钱使得转账后 B 收到 100 元。
算法分析
即A经过一些人,付出手续费,最终到达B,B手里要有100,
我们可以得出公式 Aw1w2w3w4*……=100
要A尽可能小,即w1w2w3w4……尽可能大,我们可以将人看作点,手续费看作权值,即转化为从A到B经过的权值乘积最大的一条路径
这里用spfa来求解;
spfa求最短路的本质是当dist[j]>dist[t]+w[i]时进行更新,在本题中可以转化为
if(dist[i]<dist[u]*w[u][i])
dist[i]=dist[u]*w[u][i];
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=2009;
int n,m;
int x,y;
bool st[N];
double w[N][N],dist[N];
void spfa()
{
queue<int>q;
dist[x]=1;
q.push(x);
st[x]=true;
while(q.size())
{
int u=q.front();
q.pop();
st[u]=false;
for(int i=1;i<=n;i++)
{
//!!!!!!!结和题目做的变形
if(dist[i]<dist[u]*w[u][i])
{
dist[i]=dist[u]*w[u][i];
if(!st[i])
{
q.push(i);
st[i]=true;
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b;
double c;
cin>>a>>b>>c;
c=(100.0-c)/100;
w[a][b]=w[b][a]=max(w[a][b],c);
}
cin>>x>>y;
//特殊的,dist的值要初始化为0,0不能用memset初始化,这里用fill
fill(dist+1,dist+n+1,0);
spfa();
printf("%.8lf\n",100/dist[y]);
return 0;
}