题目描述
在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。
输入
输入包含多组测试用例。
对于每组样例,第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。(0<n<=2000)以下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
题解代码如下
#include <bits/stdc++.h>
using namespace std;
struct edge{
int to;
double cost; ///保留率
};
const int N = 2010;
vector<edge> v[N];
int vis[N];
double dist[N];
int n,m,s,t;
void dij(){
memset(vis,0,sizeof vis);
memset(dist,0,sizeof dist);
for(int i=0;i<v[s].size();i++) dist[v[s][i].to] = v[s][i].cost; ///首先将距离初始化
vis[s] = 1;
for(int i=1;i<n;i++){ ///n-1个顶点只需要循环n-1次
double maxv = -99999999; ///这里条件改了一下,会发现求的是最大生成树
int maxIndex = -1;
for(int j=1;j<=n;j++){
if(!vis[j]&&maxv<dist[j]) maxv = dist[j],maxIndex = j;
}
if(maxIndex==-1) break;
vis[maxIndex]=1;
for(int j=0;j<v[maxIndex].size();j++){ ///用找到的这个下标去更新 新的顶点
if(!vis[v[maxIndex][j].to]&&dist[v[maxIndex][j].to]<dist[maxIndex]*v[maxIndex][j].cost){ ///如果这个点连接的下一个点没有被访问,且到下一个点的原始距离大于经过这个点所到达的距离
dist[v[maxIndex][j].to]=dist[maxIndex]*v[maxIndex][j].cost; ///更新这个点
}
}
}
if(dist[t]==0) puts("Impossible");
else printf("%.8f\n",100/dist[t]);
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=m;i++){ ///读入m条边,读边牵涉到顶点,这是从顶点1开始读入的
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
v[x].push_back({y,1.0-1.0*z/100});
v[y].push_back({x,1.0-1.0*z/100});
}
scanf("%d%d",&s,&t);
dij();
for(int i=1;i<=n;i++) v[i].clear(); ///将顶点清空
}
return 0;
}
dijkstra算法可以求最小生成树,但这份代码改了一下条件,求的是最长路径,这也是dijkstra的板子题,但是double数据的处理以及循环的边界条件要十分注意
堆优化版本如下
#include<bits/stdc++.h>
using namespace std;
const int N = 2020;
int n,m,s,t;
struct edge{
int to;
double w; ///表示起点到v的边权
};
struct node{
int v;
double d; ///d表示起点到d点的距离
bool operator<(const node&rs)const{
return d<rs.d;
}
};
double dist[N];
vector<edge> mp[N];
void dij(){
memset(dist,0x3f,sizeof dist);
dist[s]=1;
priority_queue<node> q;
q.push({s,1});
while(q.size()){
auto now = q.top();q.pop();
if(now.d<dist[now.v]) continue;
for(int i=0;i<mp[now.v].size();i++){
auto nx = mp[now.v][i];
if(dist[nx.to]<dist[now.v]*nx.w){
dist[nx.to]=dist[now.v]*nx.w;
q.push({nx.to,dist[nx.to]});
}
}
}
printf("%.8f\n",100/dist[t]);
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
mp[x].push_back({y,1.0-1.0*z/100});
mp[y].push_back({x,1.0-1.0*z/100});
}
scanf("%d%d",&s,&t);
dij();
for(int i=1;i<=n;i++) mp[i].clear();
}
return 0;
}