【图论】【最短路】最小花费
发布日期:2021-05-07 00:22:56 浏览次数:25 分类:原创文章

本文共 1401 字,大约阅读时间需要 4 分钟。

Description

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

Input

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

Output

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

Sample Input

3 3
1 2 1
2 3 2
1 3 3
1 3

Sample Output

103.07153164

Hint

对于所有数据,1<=n<=2000。


解题思路

明明是个无向图,为什么 f [ k ] [ j ] f[k][j] f[k][j]就对了, f [ j ] [ k ] f[j][k] f[j][k]就错了 😐


输入: 输入的是扣去多少,但是只存能得到多少,最短路变成最长路。
初值: 要给 d i s dis dis赋初值
过程中: 因为是百分数,所以求的过程中不能用+,要用乘法求
输出:
∵ 答案 x 能得到的百分数 = 100
∴ 100 / 能得到的百分数 = 答案


#include<iostream>#include<cstdio>#include<iomanip>using namespace std;int n,m,v[3000],S,T,x,y,z;double dis[3000],f[3000][3000];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-z*1.0)/100;		//扣去z%,那么就得到(100-z)%	}	scanf("%d%d",&S,&T);    for(int i=1;i<=n;++i)        dis[i]=f[S][i];//先把与S相连的点更新完    dis[S]=1;//因为用乘法,所以起点为0,不管乘多少都为0    v[S]=1;    for(int i=2;i<=n;++i){   //起点上面已经做了    	double minn=0;    	int k=0;    	for(int j=1;j<=n;++j)    	    if(!v[j]&&dis[j]>minn){   //找最小变成找最大    	    	minn=dis[j];    	    	k=j;    	    }    	if(!k) break;    	v[k]=1;    	for(int j=1;j<=n;j++)    	    if(!v[j])    	       dis[j]=max(dis[j],dis[k]*f[k][j]);    	       //最长路    	       //用乘法    }     printf("%.8lf",100/dis[T]);    return 0;}
上一篇:【图论】【最短路】USACO 2.4 牛的旅行 (最短路)
下一篇:【图论】【最短路】最短路径问题

发表评论

最新留言

表示我来过!
[***.240.166.169]2025年03月18日 11时24分27秒