• AOJ2249 最短路+最小花费(双权值)


    写题解之前先骂一下这道题

    xxx给数据范围点数<1e4,边数<2e4,结果我开2e4和3e4都RE,然后找问题一个多小时,最后我开了1e5和2e5,题面太能唬人了吧!?真是sb题面

    ------------------------------------------分割线------------------------------------

    题目大意:给n个点和m条边,每条边给了起始点,距离和价格,求在保证点1到其他n-1个点的路径都是最短路的前提下所有路的价格之和的最小值

    简单的Dijkstra变形,在松弛的时候做一下改变即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cstring>
     5 #define mem(a,b) memset(a,b,sizeof(a))
     6 using namespace std;
     7 struct edge
     8 {
     9     int to,nex,v,p;
    10 }e[220000];
    11 int cnt,dis[110000],pri[110000];
    12 int vis[110000],fir[110000];
    13 struct node
    14 {
    15     int dis,pos;
    16     node(){};
    17     node(int a,int b):dis(a),pos(b){}
    18     bool operator<(const node &x)const
    19     {
    20         return dis>x.dis;
    21     }
    22 };
    23 void add_e(int fro,int to,int v,int p)
    24 {
    25     e[++cnt].v=v;
    26     e[cnt].to=to;
    27     e[cnt].nex=fir[fro];
    28     e[cnt].p=p;
    29     fir[fro]=cnt;
    30 }
    31 void dij(int s)
    32 {
    33     priority_queue<node>q;
    34     q.push(node(0,1));
    35     while(!q.empty())
    36     {
    37         int now=q.top().pos;
    38         q.pop();
    39         if(vis[now]) continue;
    40         vis[now]=1;
    41         for(int i=fir[now];i;i=e[i].nex)
    42         {
    43             int to=e[i].to;
    44             if(dis[to]>dis[now]+e[i].v&&vis[to]==0)
    45             {
    46                 dis[to]=dis[now]+e[i].v;
    47                 pri[to]=e[i].p;     /*松弛以后更改花费,因为是由上一个点扩展来的,为了避免重复计数,
    48                                     花费直接就是边的价格,
    49                                     不理解的话可以这样想,所有的点都是由上一个点找到的,
    50                                     然后最终会到第一个点,所以总的花费=这个点的花费+之前点的花费,一直推直到点1*/
    51                 q.push(node(dis[to],to));
    52             }
    53             else if(dis[to]==dis[now]+e[i].v)//注意此处一定要用else if,因为上一个if进行之后,这个if必定满足(或者把这个if写在前面)
    54             {
    55                 pri[to]=min(e[i].p,pri[to]);//距离相同选择最小花费
    56             }
    57         }
    58     }
    59 }
    60 void ini()
    61 {
    62     cnt=0;
    63     fill(dis,dis+110000,99999999);
    64     fill(pri,pri+110000,99999999);
    65     mem(fir,0);
    66     mem(e,0);
    67     mem(vis,0);
    68 }
    69 int main()
    70 {
    71     int m,n;
    72     while(scanf("%d%d",&n,&m)&&m+n)
    73     {
    74         ini();
    75         dis[1]=0;
    76         for(int i=1;i<=m;i++)
    77         {
    78             int a,b,c,d;
    79             cin>>a>>b>>c>>d;
    80             add_e(a,b,c,d);
    81             add_e(b,a,c,d);
    82         }
    83         dij(1);
    84         int ans=0;
    85         for(int i=2;i<=n;i++)
    86         {
    87             ans+=pri[i];//加起来就是总的花费
    88         }
    89         printf("%d
    ",ans);
    90     }
    91     return 0;
    92 }
    View Code
  • 相关阅读:
    大话Ansible Ad-Hoc命令
    Ansible常用模块基本操作
    Java集合类总结
    HTTP文件上传原理
    Java IO流基础总结
    Java中的Enumeration、Iterable和Iterator接口详解
    网页缓存相关的HTTP头部信息详解
    4. OpenCV-Python——模版匹配、直方图
    3. OpenCV-Python——图像梯度算法、边缘检测、图像金字塔与轮廓检测与傅里叶变换
    2. OpenCV-Python——阈值、平滑处理、形态学操作
  • 原文地址:https://www.cnblogs.com/codeoosacm/p/10066953.html
Copyright © 2020-2023  润新知