aoj2249 最短路中的双权值问题
Posted oldataraxi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了aoj2249 最短路中的双权值问题相关的知识,希望对你有一定的参考价值。
Problem H: Road Construction
King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazingly, there are no roads in the kingdom now. Recently, he planned to construct roads between the capital and the cities, but it turned out that the construction cost of his plan is much higher than expected.
In order to reduce the cost, he has decided to create a new construction plan by removing some roads from the original plan. However, he believes that a new plan should satisfy the following conditions:
For every pair of cities, there is a route (a set of roads) connecting them.
The minimum distance between the capital and each city does not change from his original plan.
Many plans may meet the conditions above, but King Mercer wants to know the plan with minimum cost. Your task is to write a program which reads his original plan and calculates the cost of a new plan with the minimum cost.
Input
The input consists of several datasets. Each dataset is formatted as follows.
N M
u1 v1 d1 c1
.
.
.
uM vM dM cM
The first line of each dataset begins with two integers, N and M (1 ≤ N ≤ 10000, 0 ≤ M ≤ 20000). N and M indicate the number of cities and the number of roads in the original plan, respectively.
The following M lines describe the road information in the original plan. The i-th line contains four integers, ui, vi, di and ci (1 ≤ ui, vi ≤ N , ui ≠ vi , 1 ≤ di ≤ 1000, 1 ≤ ci ≤ 1000). ui , vi, di and ci indicate that there is a road which connects ui-th city and vi-th city, whose length is di and whose cost needed for construction is ci.
Each road is bidirectional. No two roads connect the same pair of cities. The 1-st city is the capital in the kingdom.
The end of the input is indicated by a line containing two zeros separated by a space. You should not process the line as a dataset.
Output
For each dataset, print the minimum cost of a plan which satisfies the conditions in a line.
Sample Input
3 3
1 2 1 2
2 3 2 1
3 1 3 2
5 5
1 2 2 2
2 3 1 1
1 4 1 1
4 5 1 1
5 3 1 1
5 10
1 2 32 10
1 3 43 43
1 4 12 52
1 5 84 23
2 3 58 42
2 4 86 99
2 5 57 83
3 4 11 32
3 5 75 21
4 5 23 43
5 10
1 2 1 53
1 3 1 65
1 4 1 24
1 5 1 76
2 3 1 19
2 4 1 46
2 5 1 25
3 4 1 13
3 5 1 65
4 5 1 34
0 0
Output for the Sample Input
3
5
137
218
给出若干双向边,每条边有长度和花费.保证从0点到其他每个点的最短路不变,删除若干边.求保留边的总花费最小值.
相当于现在的路有两个权值,那么我们就开两个数组c和d,d还是代表到顶点的最短路,c代表花的钱.现在考虑这么一件事:如果c[i]代表到顶点i的这条最短路上花的钱,那么不同的路可能有"公用"的部分,你是很难直接求出来要花的钱的.但是注意:我们最后得到的应该是一颗树,就是说,最后得到的那颗"树"里面的每一条边都是被包含在最短路里面的,每一条边都有用,因此我们只要记录每一个顶点的最短路中与它直接相连的一条边,然后把所有的这种边拼起来,就是最后要的那棵树,把这种边加起来得到的结果就是最终结果.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<queue> 7 #include<cmath> 8 9 10 using namespace std; 11 12 const int MAX_V = 10001; 13 const int MAX_E = 20001; 14 const int INF = 1e9+7; 15 16 int m, n; 17 18 typedef pair<int, int> P; 19 20 struct edge { 21 int from, to, len, cost; 22 }; 23 24 int d[MAX_V];//从起点出发到任意一点的最短路 25 int c[MAX_V];//money... 26 27 28 vector<edge>es[MAX_V+1];//邻接矩阵 29 30 void init(){ 31 for (int i = 1; i <= MAX_V;i++){ 32 es[i].clear(); 33 } 34 } 35 36 37 //就是求单源最短路的 38 void dijkstra(int s) { 39 for (int i = 1; i <= n; i++) { 40 d[i] = INF; 41 c[i] = INF; 42 } 43 d[s] = 0; 44 c[s] = 0; 45 priority_queue<P, vector<P>, greater<P> > que; 46 que.push(P(0, s)); 47 while (!que.empty()) { 48 P p = que.top(); que.pop(); 49 int v = p.second; 50 if (d[v] < p.first)continue; 51 for (int i = 0; i < es[v].size(); i++) { 52 edge e = es[v][i]; 53 if (d[e.to] > d[e.from] + e.len) { 54 d[e.to] = d[e.from] + e.len; 55 c[e.to] = e.cost; 56 que.push(P(d[e.to], e.to)); 57 }else if(d[e.to]==d[e.from]+e.len&&c[e.to]>e.cost){ 58 c[e.to] = e.cost; 59 } 60 61 62 } 63 } 64 65 } 66 67 int main(){ 68 cin>>n>>m; 69 while(m!=0||n!=0){ 70 while(m--){ 71 edge temp; 72 scanf("%d%d%d%d", &temp.from, &temp.to, &temp.len, &temp.cost); 73 es[temp.from].push_back(temp); 74 swap(temp.from, temp.to); 75 es[temp.from].push_back(temp); 76 } 77 dijkstra(1); 78 79 long long ans = 0; 80 for (int i = 1; i <= n;i++){ 81 ans += c[i]; 82 } 83 cout << ans << endl; 84 init(); 85 cin >> n >> m; 86 } 87 88 return 0; 89 }
以上是关于aoj2249 最短路中的双权值问题的主要内容,如果未能解决你的问题,请参考以下文章
AOJ 2249 Road Construction (dijkstra)
HDU - 3790最短路径问题(DIjkstra算法 双权值)