P1576 最小花费

题意分析

在 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;
 } 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值