在n我的中,某些人的銀行帳號之間能夠互相轉帳。這些人之間轉帳的手續費各不相同。給定這些人之間轉帳時須要從轉帳金額里扣除百分之幾的手續費,請問A最少須要多少錢使得轉帳後B收到100元。ios
第一行輸入兩個正整數n,m,分別表示總人數和能夠互相轉帳的人的對數。
如下m行每行輸入三個正整數x,y,z,表示標號爲x的人和標號爲y的人之間互相轉帳須要扣除z%的手續費 (z<100)。
最後一行輸入兩個正整數A,B。數據保證A與B之間能夠直接或間接地轉帳。spa
輸出A使得B到帳100元最少須要的總費用。精確到小數點後8位。code
3 3
1 2 1
2 3 2
1 3 3
1 3ci
103.07153164io
1<=n<=2000class
這一題數據較大,因此用Dijkstra,\(O(n^2)\) 實現。因爲從一個帳戶轉錢到另一個帳戶的手續費不一樣,因此咱們視它們爲邊的權值。先求出去掉手續費後所遺留下的錢,並在尋找路徑時儘可能去找能留下更多錢的路徑(注意在起始點時要給它賦值爲1),並將權值相乘,最後拿100除以權值相乘獲得的最大值,輸出答案。stream
#include <iostream> #include <cstdio> using namespace std; const int M = 2002; int n,m,a,b,k; double map[M][M],minn; double dis[M]; bool vis[M]; void dijkstra(int start) { for(int i=1; i<=n; i++) dis[i]=map[start][i]; vis[start]=true; dis[start]=1;//必須進行賦值1,由於若進行更改將使用乘法(0*every==0) for(int i=1; i<n; i++) { minn=0; for(int j=1; j<=n; j++) if(!vis[j]&&dis[j]>minn) //尋找剩餘金額最大的 minn=dis[j],k=j; vis[k]=true; if(k==b) break;//結束標誌 for(int q=1; q<=n; q++) if(!vis[q]&&dis[q]<dis[k]*map[k][q]) dis[q]=dis[k]*map[k][q];//進行鬆弛 } } int main() { double z; scanf("%d%d",&n,&m); for(int i=1,x,y; i<=m; i++) { cin>>x>>y>>z; map[x][y]=map[y][x]=(100-z)/100;//表示是原金額的百分之幾 } cin>>a>>b; dijkstra(a); printf("%.8lf\n",100/dis[b]); return 0; }