【SSL 2206】最小花費【最短路 Dijkstra】【圖論】

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。

分析&說明:

這道題用Dijkstra的方法,要先求出預處理的匯率:(100-稅率)/100。還要注意,因爲要使匯率最大,所以要將小於 < 改爲大於 > ,還要把 +改爲 * ,最後輸出要用100/結果,算法部分就是套模板。

CODE:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,x,y,l,st,ed;
double f[2002][2002],b[2002],t,z;
bool u[2002];
int main()
{
	scanf("%d %d",&n,&m);
	for (int i=1;i<=m;i++)
	  {
	  	scanf("%d %d %lf",&x,&y,&z);
	  	f[x][y]=f[y][x]=(100-z)/100;  //預處理求匯率
	  }
	scanf("%d %d",&st,&ed);
	for (int i=1;i<=n;i++)
	  b[i]=f[st][i]; //從第一個點延伸
	b[st]=1;
	u[st]=true; //記錄
	for (int i=2;i<n;i++)
	  {
	  	t=0;
	  	l=0;
	  	for (int j=1;j<=n;j++)
	  	  if ((!u[j])&&(b[j]>t))
	  	    {
	  	    	t=b[j];//代替
	  	    	l=j;//記錄
	  	    }
	  	if (!l) break;  //若無最大的,就退出
	  	u[l]=true;
	  	for (int j=1;j<=n;j++)
	  	  if ((!u[j])&&(b[l]*f[l][j]>b[j]))  //找更優的
	  	    b[j]=b[l]*f[l][j]; //再替換
	  }
	printf("%.8lf",100/b[ed]);  //注意100/結果
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章