第三部分 数据结构 --第四章 图论算法1344:【例4-4】最小花费

1344:【例4-4】最小花费

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 4204 通过数: 1843
【题目描述】
在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≤n≤2000


思路:
Dijkstra
(1)a [ i ] [ j ] 存转账率

(2)dis [ i ] 是 a [ 起点 ] [ i ]

(3)f [ i ] 判断是否已经尝试过

(4)前驱结点 k


所求的结果 :ans * a[x][y]=100 即 ans=100 / a[x][y]


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 2001
using namespace std;
double a[N][N],dis[N],minn;
int f[N],n,m,k,x,y;
void read(){
	int xx,yy,zz;
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; i++)
	{
		scanf("%d%d",&xx,&yy);
		scanf("%lf",&a[xx][yy]);
		a[xx][yy] = (100 - a[xx][yy])/100;
		a[yy][xx] = a[xx][yy];
		}
		cin >> x >> y;
	}
	void dijkstra(int x){//dijkstra 算法
		for(int i = 1; i <= n; i++)
		dis[i] = a[x][i];
		dis[x] = 1;
		f[x] = 1;
		for(int i = 1; i <= n-1;i++)
		{
			minn = 0;
			for(int j = 1; j <= n; j++)
			if(!f[j] && dis[j] > minn)
			{
				k = j;
				minn = dis[j];
			}
			f[k] = 1;
			if(k == y) break;
			for(int j = 1; j <= n; j++)
			if(!f[j] && dis[k]*a[k][j] > dis[j])
			dis[j] = dis[k] * a[k][j];
		}
	}
	int main(){
		read();
		dijkstra(x);
		printf("%.8lf",100/dis[y]);//ans * a[x][y]=100 即 ans=100 / a[x][y]
		return 0;
	}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章