公路村村通
Posted onlyblues
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了公路村村通相关的知识,希望对你有一定的参考价值。
公路村村通
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤ 1000)和候选道路数目M(≤ 3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15 1 2 5 1 3 3 1 4 7 1 5 4 1 6 2 2 3 4 2 4 6 2 5 2 2 6 6 3 4 6 3 5 1 3 6 1 4 5 10 4 6 8 5 6 3
输出样例:
12
解题思路
最小生成树模板题。
Prime算法的AC代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <queue> 5 #include <map> 6 7 const int INF = 0x3f3f3f3f; 8 9 typedef std::pair<int, int> Pair; 10 11 struct Edge { 12 int to, wt; 13 }; 14 15 struct Graph { 16 std::vector<std::vector<Edge> > G; 17 int verN, edgeN; 18 }; 19 20 Graph *createGraph(int n, int m); 21 int Prime(Graph *graph, int src); 22 23 int main() { 24 int n, m; 25 scanf("%d %d", &n, &m); 26 Graph *graph = createGraph(n, m); 27 int minCost = Prime(graph, 0); 28 printf("%d", minCost); 29 30 return 0; 31 } 32 33 Graph *createGraph(int n, int m) { 34 Graph *graph = new Graph; 35 graph->verN = n; 36 graph->edgeN = m; 37 graph->G.resize(graph->verN); 38 39 for (int i = 0; i < graph->edgeN; i++) { 40 int v, w, wt; 41 scanf("%d %d %d", &v, &w, &wt); 42 graph->G[v - 1].push_back({w - 1, wt}); 43 graph->G[w - 1].push_back({v - 1, wt}); 44 } 45 46 return graph; 47 } 48 49 int Prime(Graph *graph, int src) { 50 int dist[graph->verN]; 51 std::fill(dist, dist + graph->verN, INF); 52 bool vis[graph->verN] = {false}; 53 dist[src] = 0; 54 int vCount = 0, totalWt = 0; 55 56 std::priority_queue<Pair, std::vector<Pair>, std::greater<Pair> > pq; 57 pq.push(Pair(dist[src], src)); 58 59 while (!pq.empty()) { 60 int v = pq.top().second; 61 pq.pop(); 62 if (vis[v]) continue; 63 64 vis[v] = true; 65 vCount++; 66 totalWt += dist[v]; 67 for (std::vector<Edge>::iterator it = graph->G[v].begin(); it != graph->G[v].end(); it++) { 68 if (!vis[it->to] && it->wt < dist[it->to]) { 69 dist[it->to] = it->wt; 70 pq.push(Pair(dist[it->to], it->to)); 71 } 72 } 73 } 74 75 return vCount == graph->verN ? totalWt : -1; 76 }
Kruskal算法的AC代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <queue> 5 6 struct Edge { 7 int to, wt; 8 }; 9 10 struct Graph { 11 std::vector<std::vector<Edge> > G; 12 int verN, edgeN; 13 }; 14 15 struct Pair { 16 int from, to, wt; 17 }; 18 19 Graph *createGraph(int n, int m); 20 int Kruskal(Graph *graph); 21 bool merge(int *st, int v, int w); 22 int find(int *st, int x); 23 bool operator<(const Pair &a, const Pair &b); 24 25 int main() { 26 int n, m; 27 scanf("%d %d", &n, &m); 28 Graph *graph = createGraph(n, m); 29 int minCost = Kruskal(graph); 30 printf("%d", minCost); 31 32 return 0; 33 } 34 35 Graph *createGraph(int n, int m) { 36 Graph *graph = new Graph; 37 graph->verN = n; 38 graph->edgeN = m; 39 graph->G.resize(graph->verN); 40 41 for (int i = 0; i < graph->edgeN; i++) { 42 int v, w, wt; 43 scanf("%d %d %d", &v, &w, &wt); 44 graph->G[v - 1].push_back({w - 1, wt}); 45 graph->G[w - 1].push_back({v - 1, wt}); 46 } 47 48 return graph; 49 } 50 51 int Kruskal(Graph *graph) { 52 std::priority_queue<Pair> pq; 53 for (int v = 0; v < graph->verN; v++) { 54 for (std::vector<Edge>::iterator it = graph->G[v].begin(); it != graph->G[v].end(); it++) { 55 pq.push({v, it->to, it->wt}); 56 } 57 } 58 int st[graph->verN]; 59 std::fill(st, st + graph->verN, -1); 60 int eCount = 0, totalWt = 0; 61 62 while (!pq.empty()) { 63 int v = pq.top().from; 64 int w = pq.top().to; 65 int wt =pq.top().wt; 66 pq.pop(); 67 if (merge(st, v, w)) { 68 eCount++; 69 totalWt += wt; 70 } 71 } 72 73 return eCount == graph->verN - 1 ? totalWt : -1; 74 } 75 76 bool merge(int *st, int v, int w) { 77 v = find(st, v); 78 w = find(st, w); 79 if (v == w) return false; 80 st[v] = w; 81 return true; 82 } 83 84 int find(int *st, int x) { 85 return st[x] < 0 ? x : st[x] = find(st, st[x]); 86 } 87 88 bool operator<(const Pair &a, const Pair &b) { 89 return a.wt > b.wt; 90 }
以上是关于公路村村通的主要内容,如果未能解决你的问题,请参考以下文章