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

Posted codeoosacm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于AOJ2249 最短路+最小花费(双权值)的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 3790最短路径问题(DIjkstra算法 双权值)

AOJ-2249-Road Construction-dijkstra-最小花费

AOJ 2249 Road Construction (dijkstra)

POJ3013-Big Christmas Tree-最短路

HDU3790---(双权最短路径)

[最短路] aw1126. 最小花费(单源最短路建图+知识理解+代码细节+好题)