最小花费 (Dijkstra算法)

最小花费

题目

n n n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问 A A A最少需要多少钱使得转账后 B B B收到100元。


输入

第一行输入两个用空格隔开的正整数 n n n m m m,分别表示总人数和可以互相转账的人的对数。以下m行每行输入三个用空格隔开的正整数 x x x , y y y , z z z,表示标号为x的人和标号为y的人之间互相转账需要扣除 z z z%的手续费 ( z < 100 ) ( z < 100 ) (z<100)。最后一行输入两个用空格隔开的正整数 A A A B B B。数据保证 A A A B B B之间可以直接或间接地转账。


输出

输出 A A A使得 B B B到账100元最少需要的总费用。精确到小数点后8位。


样例

input
3 3
1 2 1
2 3 2
1 3 3
1 3

output
103.07153164


解题思路

逆转思维一下,求出拿走手续费后 B B B拿到的钱占原本的钱的百分比, B B B拿的一定是100,用100除以那个百分比就等于最小花费
说明 费用乘一个百分数=100
使得 费用最小
所以 那个百分数最大


代码

#include
#include
using namespace std;
int n,m,x,y,z,s,t,p[2200];
double f[2200][2200],c[2200];
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
	    scanf("%d%d%d",&x,&y,&z);
	    f[x][y]=f[y][x]=(100.0-z)/100; //求出去掉手续费后能拿到的钱的百分比
	}
	scanf("%d%d",&s,&t);
	p[s]=1;
	for (int i=1;i<=n;i++)
	    c[i]=f[s][i];  //初始赋初值
	for (int i=1;i<n;i++)
	{
		int k=0;
		double mi=0.0;
		for (int j=1;j<=n;j++)
		    if (p[j]==0&&mi<c[j])
		    {
		    	k=j;
		    	mi=c[j];  //找到找大的一个百分数
		    }
		p[k]=1;  //标记做过
		for (int j=1;j<=n;j++)
		    if (p[j]==0&&c[k]*f[k][j]>c[j])
		       c[j]=c[k]*f[k][j];  //更新未走过的点能拿到的最大的百分数
	}
	printf("%.8lf",100/c[t]);  //100除以这个百分数得出最小花费
	return 0;
}

你可能感兴趣的:(最短路)