zoukankan      html  css  js  c++  java
  • 洛谷P1576 最小花费

    坑题!!!!!
    大下午yyf给我发了这么一道题,初看还没有思路。(第一次这么认真的写图论
    blog)
    题面:

    在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手
    续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续
    费,请问A最少需要多少钱使得转账后B收到100元。

    初看很懵逼
    但是仔细分析+算法标签可以发现
    这个题是有关于最短路的题
    为什么说?
    因为我们可以建个图,人是点而手续费是边,手续费是边权。这个题初步建模
    就完成了。
    但是,这个题还是写不出来。
    考虑完了最短路,应该选择算法:
    floyd dijkstra spfa
    floyd显然不行 本题可以写堆优化的dijkstra或者spfa
    确定算法之后发现一个非常大的坑点:松弛操作没法完成。
    分析题目:
    我们用dis数组表示手续费,那么dis[u]<dis[v]*edge[i].dis就是条件
    为什么?
    dis[u]<他俩的乘积的话,那么这个dis[u]就不是当前的最短路
    要求A花最少的钱->B获得100元
    说明了要求dis[B]尽量小
    所以就要把这个当成松弛的条件
    坑点没有完,还有个非常坑人的操作:Z是整数!
    在dis数组中,这玩意显然要写成实数,所以要预处理,/100之后再进行加边。
    完成了这些,题目还是没有解完。求得dis[B]是最小的汇率,我们再想100元是
    怎么来的:要花的钱数*dis[B]=100
    逆向思维,ans=100/dis[B]
    保留小数。

    C++:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<queue>
    #include<set>
    #include<stack>
    #include<map>
    #include<algorithm>
    #define maxn 100001
    #define INF 0x3f3f3f3f
    #define inf 0x3f
    #define maxm 1001
    using namespace std;
    int num_edge,head[maxn],vis[maxn],n,A,B,m,x,y;
    queue<int> q;
    double dis[maxn],z,ans;
    struct edge{
        int to,nxt;
        double dis;
    }edge[1000005];
    inline void clear(){
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
    }
    inline void addedge(int from,int to,double dis){
        edge[++num_edge].nxt=head[from];
        edge[num_edge].dis=1-dis;
        edge[num_edge].to=to;
        head[from]=num_edge;
    }
    void spfa(int s){
        q.push(s);
        dis[s]=1;
        vis[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=edge[i].nxt){
                int v=edge[i].to;
                if(dis[v]<dis[u]*edge[i].dis){
                    dis[v]=dis[u]*edge[i].dis;
                    if(vis[v]==0){
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    int main(){
        cin>>n>>m;
        clear();
        for(int i=1;i<=m;i++){
            cin>>x>>y>>z;
            addedge(x,y,z/100);
            addedge(y,x,z/100);
        }
        cin>>A>>B;
        //dis[A]=1;
        spfa(A);
        ans=100/dis[B];
        printf("%.8lf",ans);
        return 0;
    }
  • 相关阅读:
    zencart_magiczoom
    如何把一个TXT文本文件按行数分割成多个文本文件
    工作时常用东西汇总
    asp Vernum
    sitemap制作
    php后门屌炸天
    威盾解密
    软路由
    企业安全工作要点
    内网ARP攻击
  • 原文地址:https://www.cnblogs.com/kenlig/p/9495076.html
Copyright © 2011-2022 走看看