Aizu2249 Road Construction(dijkstra优化+思路 好题)

https://vjudge.net/problem/Aizu-2249

感觉这题和2017女生赛的Deleting Edge思路很像,都是先找最短路,然后替换边的。

但是这题用最朴素的dijkstra的话memory limit exceed了,看了下超了约7倍无望。。。

不得已这时候不得不学dijkstra的堆优化了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<stack>
 8 #define lson l, m, rt<<1
 9 #define rson m+1, r, rt<<1|1
10 #define INF 0x3f3f3f3f
11 typedef unsigned long long ll;
12 using namespace std;
13 int n, m, a, b, d, c;
14 int dist[1010], t[1010][10010], p[1010][1010];
15 int vis[1010];
16 void dijkstra()
17 {
18     memset(vis, 0, sizeof(vis));
19     for(int i = 1; i <= n; i++){
20         dist[i] = INF;
21     }
22     dist[1] = 0;
23     for(int i = 1; i <= n; i++){
24         int mini = INF, k = -1;
25         for(int j = 1; j <= n; j++){
26             if(!vis[j]&&mini > dist[j]){
27                 mini = dist[j];
28                 k = j;
29             }
30         }
31         vis[k] = 1;
32         for(int j = 1; j <= n; j++){
33             if(!vis[j]&&dist[j] > dist[k]+t[k][j]){
34                 dist[j] = dist[k]+t[k][j];
35             }
36         }
37     }
38 } 
39 int main()
40 {
41     while(cin >> n >> m){
42         if(!n&&!m) break;
43         for(int i = 1; i <= n; i++){
44             for(int j = 1; j <= n; j++){
45                 if(i == j) t[i][j] = 0, p[i][j] = 0;
46                 else t[i][j] = INF; p[i][j] = INF;
47             }
48         }
49         for(int i = 0; i < m; i++){
50             cin >> a >> b >> d >> c;
51             t[a][b] = d; t[b][a] = d;
52             p[a][b] = c; p[b][a] = c;
53         }
54         dijkstra(); 
55         int sum=0;
56         for(int i = 2; i <= n; i++){//这里记得要从2开始,从一开始下面无法更新mini,而且反正i=1的时候mini也是0,就直接跳过了 
57             int mini = INF;
58             for(int j = 1; j <= n; j++){
59                 if((dist[i] == dist[j]+t[j][i])&&mini>p[j][i]){
60                     mini = p[j][i];
61                 }
62             }
63             sum += mini;
64         }
65         cout << sum << endl;
66     }
67     return 0;
68 }

 优先队列、vector容器、pair优化

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<stack>
 8 #define lson l, m, rt<<1
 9 #define rson m+1, r, rt<<1|1
10 #define INF 0x3f3f3f3f
11 typedef unsigned long long ll;
12 using namespace std;
13 int n, m, a, b, d, c;
14 int dist[10010];
15 struct edge{
16     int to, d, cost;
17     //edge(int a, int b, int c):to(a),d(b),cost(c){ } 
18 };
19 typedef pair<int, int> P;
20 vector<edge> G[10010];
21 void dijkstra()
22 {
23     priority_queue<P, vector<P>, greater<P> > q;
24     for(int i = 1; i <= n; i++) dist[i] = INF;
25     dist[1] = 0;
26     q.push(P(0, 1));
27     while(!q.empty()){
28         P p = q.top(); q.pop();
29         int v = p.second;
30         if(dist[v] < p.first) continue;
31         for(int i = 0; i < G[v].size(); i++){
32             edge e = G[v][i];
33             if(dist[e.to] > dist[v]+e.d){
34                 dist[e.to] = dist[v]+e.d;
35                 q.push(P(dist[e.to], e.to));
36             }
37         }
38     }
39 } 
40 int main()
41 {
42     while(cin >> n >> m){
43         if(!n&&!m) break;
44         for(int i = 0; i <= n; i++){
45             G[i].clear();
46         }
47         for(int i = 0; i < m; i++){
48             cin >> a >> b >> d >> c;
49             G[a].push_back(edge{b, d, c});
50             G[b].push_back(edge{a, d, c});
51         }
52         dijkstra(); 
53         /*for(int i = 1; i <= n; i++){
54             cout << dist[i] << " ";
55         }*/
56         int sum = 0;
57         for(int i = 2; i <= n; i++){
58             int mini = INF;
59             for(int j = 0; j < G[i].size(); j++){
60                 edge e = G[i][j];
61                 if(dist[e.to]+e.d == dist[i]){//这里注意,一开始e.d错放到等式右边了 
62                     mini = min(mini, e.cost);
63                 }
64             }
65             sum += mini;
66         }
67         cout << sum << endl;
68     }
69     return 0;
70 }

 

转载于:https://www.cnblogs.com/Surprisezang/p/9017356.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值