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

    题目描述:

      传送门

    题解思路:

      假设初始转账人为A,最终接账人为B。看起来感觉直接求A转账的钱并不好求,但是可以通过已经B收到的金额,再返回去推A转账的金额,一种逆序的思想,每次推算下一个点的时候都要除以(1-z%)往回推转账的钱,所有都逆过来了,因此很明显这道题是一个裸的最短路径问题。此题用dijkstra算法即可求解,唯一需要注意的是,更新点的权值不再是加法而变成了此题的乘法。

      注意:题目所给的边的上限不是很可靠,导致最后又2个点RE,然后修改边结构体的大小为原来的10倍才通过。

    代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm> 
     4 #include<queue> 
     5 #include<cstdio>
     6 using namespace std;
     7 int INFTY=1<<30;                //一个较大的值 
     8 #define re register
     9 
    10 typedef pair<double,int> P;                //前面存到起始点的值,后面存点编号 
    11 struct edge{
    12     int next;        //下一条的编号 
    13     double w;            //权值 
    14     int to;            //当前边的终止点编号 
    15 };
    16 edge e[1000005];
    17 int head[2005];
    18 int cnt=0;
    19 int n,m; 
    20 int WHITE=0;
    21 int BLACK=1;
    22 int GRAY=2;
    23 
    24 void dij(int start,int end){    //start实际上是收账人,end是转账人 
    25     priority_queue<P,vector<P>,greater<P> > que;        //最小值优先
    26     double d[2005];                //存个点到起点的值
    27     int color[2005];
    28     
    29     for(re int i=1;i<=n;i++){
    30         color[i]=WHITE;        //表示未访问过
    31         d[i]=INFTY;            //表示没有连接 
    32     } 
    33     que.push(P(100,start));                //起点入队
    34     color[start]=GRAY;                        //记录访问过
    35     d[start]=100;                        //100起步 
    36     
    37     while(!que.empty()){
    38         P cur=que.top();
    39         que.pop();
    40         int u=cur.second;                //拿出点的编号
    41         
    42         if(color[u]==BLACK) continue;  
    43         color[u]=BLACK;
    44         
    45         for(re int k=head[u];~k;k=e[k].next){        //遍历和temp有关的所有边 
    46             if(color[e[k].to]==BLACK) continue;            //表示没访问过 
    47             
    48             int v=e[k].to;            //边的终点 
    49             double money=d[u]/(1-(e[k].w)/100);
    50             if(money<d[v]){                //注意要进行点的权值比较,若点权值能变小才会更新 
    51                 que.push(P(money,v));
    52                 d[v]=money;
    53                 color[v]=GRAY;
    54             }
    55         }
    56     }
    57     
    58     printf("%0.8lf",d[end]);            //输出最终某个人需要转账时的最小花费 
    59 }
    60 void add(int a,int b,double c){    //前向星存图 
    61     e[cnt].to=b;
    62     e[cnt].w=c;
    63     e[cnt].next=head[a];
    64     head[a]=cnt;
    65     cnt++;
    66 }
    67 int main(){
    68     memset(head,-1,sizeof(head));
    69     cin>>n>>m;
    70     
    71     for(re int i=1;i<=m;i++){
    72         int a,b;
    73         double c;
    74         cin>>a>>b>>c;
    75         add(a,b,c);                    //无向图存图 
    76         add(b,a,c);
    77     }
    78     
    79     int a,b;
    80     cin>>a>>b;
    81     dij(a,b);
    82     return 0;
    83 }
  • 相关阅读:
    登陆的一个大概流程
    过滤器实现编码过滤处理
    注册的一个大概流程
    lstm clip
    gemm c++
    lstm的debug模式下编译不行貌似
    caffe编译关于imread问题的解决
    c++ 走向高级之日积月累
    c++ 线程
    InitGoogleLogging坑爹
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12827389.html
Copyright © 2011-2022 走看看