P1576 最小花费
1.审题
1.使得转账后 B 收到 100 元。
2.互相转账
3. z%的手续费(z<100)
2.思路
1.dijkstra算法(很讨厌这种算法名字):把已探访过的点的下一个点中“ ‘还没探访过的点’的更新”放进堆里,堆里弹出未探访点的第一个更新便是该点的最值
2.准备工作,把所有的边放进树形链表(我觉得叫跳跃型更形象)里,对于链表中的每一个元素,都有head(同属于一个起点的、先一步放进去的、并列的边的下标),to(边的终点),cost(边的值),latest(最后一个放入链表中的以该点为起点的边的下标)
3.struct的重载比较符
3.代码
#include<bits/stdc++.h>
using namespace std;
struct
{
int to;
double cost;
int head;
}way[200005];
int latest[2005]={0};
int len=0;
void add(int x,int y,double c)
{
way[++len].to=y;
way[len].cost=c;
way[len].head=latest[x];
latest[x]=len;
}
struct unit
{
int pos;
double renew;
bool operator<(const unit &b)const
{
return b.renew<renew;
}
};
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
double c;
scanf("%d%d%lf",&x,&y,&c);
add(x,y,c);
add(y,x,c);
}
int A,B;
scanf("%d%d",&A,&B);
priority_queue<unit> q;
int vis[2005]={0};
double pay[2005]={0};
q.push(unit{B,100.0});
while(!q.empty())
{
int now=q.top().pos;
double val=q.top().renew;
q.pop();
if(!vis[now])
{
vis[now]=1;
pay[now]=val;
for(int i=latest[now];i!=0;i=way[i].head)
{
int next=way[i].to;
if(!vis[next])q.push(unit{next,pay[now]/(1-way[i].cost*1.0/100)});
}
//printf("%d: %.8lf\n",now,pay[now]);
}
}
printf("%.8lf\n",pay[A]);
return 0;
}

浙公网安备 33010602011771号