习题8.5 畅通工程之局部最小花费问题 (35point(s))
某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。
Example:
#include <iostream>
#include <vector>
#include <list>
using namespace std;
struct Edge {
int src;
int dst;
int cost;
};
vector<int> com;
vector<bool> visited;
int component;
void DFS(vector<list<Edge>> &G, int v)
{
if(visited[v]) return ;
visited[v] = true;
com[v] = component;
for(auto &x : G[v]) {
DFS(G, x.dst);
}
}
int main()
{
int N;
cin >> N;
list<Edge> edge;
vector<list<Edge>> adj(N+1);
for(int i = 0; i < N*(N-1)/2; i++) {
int src, dst, cost, build;
cin >> src >> dst >> cost >> build;
if(build == 1) {
adj[src].push_back({src, dst, cost});
adj[dst].push_back({dst, src, cost});
} else {
auto next = edge.begin();
for(; next != edge.end(); next++) {
if(cost <= next->cost) break;
}
edge.insert(next, {src, dst, cost});
}
}
com.resize(N+1);
visited.resize(N+1);
for(int i = 1; i <= N; i++) {
if(!visited[i]) {
++component;
DFS(adj, i);
}
}
int cost = 0;
if(component > 1) {
for(auto &x: edge) {
if(com[x.src] != com[x.dst]) {
cost += x.cost;
int Max = max(com[x.src], com[x.dst]);
int Min = min(com[x.src], com[x.dst]);
for(auto &y : com) {
if(y == Max) y = Min;
}
}
}
}
cout << cost << endl;
return 0;
}
思路:
- 没有建道路的边,按升序排队
- 计算连通分量
- 按照升序的待建边,连接不同的连通分量。