题目描述
在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。
输入输出格式
输入格式:
第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。
以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。
最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。
输出格式:
输出A使得B到账100元最少需要的总费用。精确到小数点后8位。
输入输出样例
说明
1<=n<=2000,m<=100000
//这个题看了不下三次了 今天终结了他 //一直担心精度问题,但是其实把int转成double可以过的 //建图的时候,让边权=1-w/100,即交完手续费后剩下的钱 //从B往A跑,dis[v]=min(dis[v],dis[u]/w[i]),这样倒着推回去,赋dis[b]初值为100 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; const int N=2e3+5; const int M=1e5+5; const int INF=599518803; int n,m,A,B; int x,y; double z; int head[N],num_edge; struct Edge { int v,nxt; double w; }edge[M<<1]; bool inque[N]; double dis[N]; int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } void add_edge(int u,int v,double w) { edge[++num_edge].v=v; edge[num_edge].w=w; edge[num_edge].nxt=head[u]; head[u]=num_edge; } void spfa() { memset(dis,INF,sizeof(dis)); //cout<<dis[3]; queue<int> que; dis[A]=100; que.push(A); int now; while(!que.empty()) { now=que.front(),que.pop(); inque[now]=0; for(int i=head[now],v;i;i=edge[i].nxt) { v=edge[i].v; if(dis[v]>dis[now]/edge[i].w) { //printf("AGO: %.8lf ",dis[v]); dis[v]=dis[now]/edge[i].w; //printf("AFT: %.8lf ",dis[v]); if(!inque[v]) { que.push(v); inque[v]=1; } } } } } int main() { n=read(),m=read(); for(int i=1;i<=m;++i) { x=read(),y=read(),scanf("%lf",&z); z/=100,z=1-z; add_edge(x,y,z); add_edge(y,x,z); } A=read(),B=read(); spfa(); printf("%.8lf",double(dis[B])); return 0; }