1. 程式人生 > >AOJ 2249 Road Construction (dijkstra)

AOJ 2249 Road Construction (dijkstra)

() pla ble func esp nal dijk writer 減少

某國王需要修路,王國有一個首都和多個城市,需要修路。已經有修路計劃了,但是修路費用太高。

為了減少修路費用,國王決定從計劃中去掉一些路,但是需要滿足一下兩點:

  1. 保證所有城市都能連通
  2. 所有城市到首都的最短路不變

思路:

在Dijkstra找最短路的時候,就記錄一下費用

if(d[e.to] > d[v] + e.dist) 
{
    ...
    prev_min_cost[e.to] = e.cost; // 最短路必經之路,則費用也必須要
}
else if(d[e.to] == d[v] + e.dist) // 最短路可選擇之路,選擇最小的費用連接
    prev_min_cost[e.to] = min(prev_min_cost[e.to], e.cost);

程序

#include <iostream>
#include <queue>
#include <functional>
#include <cstring>
using namespace std;
struct edge 
{
	int to, dist, cost;
	edge(int to, int dist, int cost) : to(to), dist(dist), cost(cost) {}
	bool operator<(const edge &b) const
	{
		return dist > b.dist;
	}
};
vector<edge> G[10005];
int N, M; // 節點數,道路數
int d[10005]; // 距離源點s(s==1)的最小距離
int prev_min_cost[10005]; // 節點的鄰接邊最小花費
int ans;
void dijkstra(int s) 
{
	memset(d, 0x3f, sizeof(d));
	memset(prev_min_cost, 0x3f, sizeof(prev_min_cost));
	d[s] = 0;
	priority_queue<edge> que;
	que.push(edge(s, d[s], 0));
	while (!que.empty()) 
	{
		edge p = que.top(); que.pop();
		int v = p.to;
		if (d[v] < p.dist) continue;
		for (int i = 0; i<G[v].size(); ++i) 
		{
			edge e = G[v][i];
			if (d[e.to] > d[v] + e.dist) 
			{
				d[e.to] = d[v] + e.dist;
				que.push(edge(e.to, d[e.to], G[v][i].cost));
				prev_min_cost[e.to] = e.cost; // 最短路必經之路,則費用也必須要
			}
			else if (d[e.to] == d[v] + e.dist) // 最短路可選擇之路,選擇最小的費用連接
				prev_min_cost[e.to] = min(prev_min_cost[e.to], e.cost);
		}
	}
}

void solve() 
{
	dijkstra(1);
	for (int u = 2; u <= N; ++u) ans += prev_min_cost[u]; // 求出所有必須的費用(n-1條邊)
	cout << ans << endl;
}

int main()
{
	int u, v, d, c;
	while (cin >> N >> M) 
	{
		for (int u = 1; u <= N; ++u) G[u].clear();
		ans = 0;
		if (N == M && N == 0) break;
		for (int i = 0; i < M; ++i) 
		{
			cin >> u >> v >> d >> c;
			G[u].push_back(edge(v, d, c)); // 構圖
			G[v].push_back(edge(u, d, c));
		}
		solve();
	}
	return 0;
}

AOJ 2249 Road Construction (dijkstra)