AOJ 2249 Road Construction (dijkstra)

某国王需要修路,王国有一个首都和多个城市,需要修路。已经有修路计划了,但是修路费用太高。

为了减少修路费用,国王决定从计划中去掉一些路,但是需要满足一下两点:

  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;
}
原文地址:https://www.cnblogs.com/demian/p/7395894.html