题目描述:

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数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

结尾无空行

分析与问题:

1、经典错误代码:

此处偷懒地没有使用并查集,仿照Prim算法中对节点是否在生成树节点集合中的标记方法,直接通过判断权值最小边的两个节点是否都被收录来判断这条边是否会在加入之后形成回路。但是,实际上,这个是错误的!!!

如下图的情况,在边1和2录入生成树中之后,显然边3是可以继续加入的!

#include<iostream>
#include<vector>
using namespace std;
#define MAX 65536
class edge {
public:int u;int v;int w;edge(int U, int V, int W) {u = U, w = W; v = V;}
};
vector<edge>edges;//存储边
void down(vector<int>& h, int i,int s) {int l = i * 2 + 1; int r = i * 2 + 2;if (l < s) {int min = l;if (r < s && edges[h[r]].w < edges[h[l]].w)min = r;int tem = h[min];h[min] = h[i];h[i] = tem;down(h, min, s);}
}
void Creat(vector<int>&h, int s) {for (int i = (s - 2) / 2; i >= 0; i--)down(h, i,s);
}
int GetTop(vector<int>& h, int& s) {if (!s)return -1;int ans = h[0];h[0] = h[--s];down(h, 0, s);return ans;
}
int main() {int N; cin >> N;int E; cin >> E; int e = E;vector<int>collected(N + 1, 0);//标记顶点是否已经被收录int u, v, w;vector<int>Heap(E);int size = E;while (e--) {cin >> u >> v >> w;edges.emplace_back(edge(u, v, w));Heap[e] = e;}Creat(Heap, size);int ans = 0;//记录最小生成树的权值之和int edge = 0;//记录边的数目while (edge != N - 1) {int num=GetTop(Heap,size);//找到剩余边集中的最小边if (num != -1) {if (!collected[edges[num].u] || !collected[edges[num].v]) {ans += edges[num].w; edge++;collected[edges[num].u] = 1;collected[edges[num].v] = 1;}//如果该边加入生成树中不会形成环,就加入,否则不加入}//如果剩余边集合中还存在边else break;}if (edge == N - 1)cout << ans;else cout << "-1";
}

2、修改使用并查集之后还是错误的代码

(还是没有发现错误在哪。有待进一步探索):

#include<iostream>
#include<vector>
using namespace std;
class edge {
public:int u;int v;int w;edge(int U, int V, int W) {u = U, w = W; v = V;}
};
vector<edge>edges;
void down(vector<int>& h, int i,int s) {int l = i * 2 + 1; int r = i * 2 + 2;if (l < s) {int min = l;if (r < s && edges[h[r]].w < edges[h[l]].w)min = r;int tem = h[min];h[min] = h[i];h[i] = tem;down(h, min, s);}
}
void Creat(vector<int>&h, int s) {for (int i = (s - 2) / 2; i >= 0; i--)down(h, i,s);
}
int GetTop(vector<int>& h, int& s) {if (!s)return -1;int ans = h[0];h[0] = h[--s];down(h, 0, s);return ans;
}
int find(vector<int>& collect, int i) {if (collect[i] < 0)return i;return  collect[i]=find(collect, collect[i]);
}
bool check(vector<int>&collect,edge e) {int u = e.u; int v = e.v;int r1 = find(collect, u);int r2 = find(collect, v);return r1 == r2;
}
void merge(vector<int>& collect, edge e) {int u = e.u; int v = e.v;int r1 = find(collect, u);int r2 = find(collect, v);if (collect[r1] < collect[r2]) {collect[r1] = collect[r1] + collect[r2];collect[r2] = r1;}else { collect[r2] = collect[r1] + collect[r2];collect[r1] = r2; }
}
int main() {int N; cin >> N;int E; cin >> E; int e = E;vector<int>collected(E, -1);int u, v, w;vector<int>Heap(E);int size = E;while (e--) {cin >> u >> v >> w;edges.emplace_back(edge(u, v, w));Heap[e] = e;}Creat(Heap, size);int ans = 0;int edge = 0;while (edge != N - 1) {int num = GetTop(Heap, size);if (num != -1) {if (!check(collected,edges[num])) {ans += edges[num].w; edge++;merge(collected, edges[num]);}}else break;}if (edge == N - 1)cout << ans;else cout << "-1";
}

3、AC代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class edge {
public:int u;int v;int w;edge(int U, int V, int W) {u = U, w = W; v = V;}
};
int find(vector<int>& collect, int i) {if (collect[i] < 0)return i;return  collect[i]=find(collect, collect[i]);
}
bool check(vector<int>&collect,edge e) {int u = e.u; int v = e.v;int r1 = find(collect, u);int r2 = find(collect, v);return r1 == r2;
}
void merge(vector<int>& collect, edge e) {int u = e.u; int v = e.v;int r1 = find(collect, u);int r2 = find(collect, v);if (collect[r1] < collect[r2]) {collect[r1] = collect[r1] + collect[r2];collect[r2] = r1;}else { collect[r2] = collect[r1] + collect[r2];collect[r1] = r2; }
}
bool cmp(const edge& a, const edge& b)
{return a.w < b.w;
}
int main() {int N; cin >> N;int E; cin >> E; int e = E;vector<edge>edges;vector<int>collected(E, -1);int u, v, w;vector<int>Heap(E);while (e--) {cin >> u >> v >> w;edges.emplace_back(edge(u, v, w));}int ans = 0;int edge = 0;sort(edges.begin() , edges.end(), cmp);for (int i = 0; i < E; i++) {int num = i;if (!check(collected, edges[num])) {ans += edges[num].w; edge++;merge(collected, edges[num]);}if (edge == N - 1)break;}if (edge == N - 1)cout << ans;else cout << "-1";
}

7-10 公路村村通 (30 分)相关推荐

  1. 7-5 公路村村通 (30 分)(C语言实现)

    现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N) ...

  2. 浙大数据结构:08-图7 公路村村通 (30 分)Prim与Kruskal算法

    08-图7 公路村村通 (30 分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N( ...

  3. 5-10 公路村村通 (30分)

    5-10 公路村村通 (30分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N( ≤ ...

  4. 7-3 公路村村通 (30分)含解析

    7-3 公路村村通 (30分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤10 ...

  5. 7-10 公路村村通 (30 分)(C语言)

    7-10 公路村村通 (30 分) (写在前面:Kruskal算法不够完善,跪求大佬指点怎么修改,拜托拜托

  6. 08-图7 公路村村通 (30分)

    是关于最小生成树的问题(包含v个顶点v-1条边,且边的权重和最小),利用Kruskal贪心算法–将边合并成树,每次都取权值最小的边并且不构成回路,就利用到了并查集的算法(用数组存父节点). 08-图7 ...

  7. 08-图7 公路村村通 (30 分)

    现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤)和候选道路数目M(≤):随后的M行 ...

  8. 7-1 公路村村通 (30 分)

    现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N) ...

  9. 公路村村通 (30分)【C语言】Prim算法 和 Kruskal算法

    目录 题目: 输入格式 输出格式 输入样例 输出样例 问题分析 最小生成树的特点 算法 Prim算法 代码实现 Prim函数:小树变大的过程中记录fee(费用和)和count(已收集的边数) Find ...

最新文章

  1. CodeBlocks 汉化教程及多语言
  2. 要学Web前端开发,你要掌握这6点知识
  3. 编写高性能Web应用程序的10个技巧
  4. 【转】datagridview的checkbox列,当修改checkbox状态时实时获得其准确状态值
  5. 如何使用分析模型 — 3. 排比图,分析问题的同时给出答案
  6. 每天拿起手机100次,使用7小时?iOS 12告诉你时间都去哪儿了
  7. 4月15日见?疑似一加8 Pro真机谍照曝光:开孔双曲面屏加持
  8. 数据库创建时间,更新时间设计
  9. MySQL------报错Access denied for user ‘root‘@‘localhost‘ (using password:NO)解决方法
  10. 【点击模型学习笔记】Modeling contextual factors of click rates_MS_AAAI2007
  11. 阿里这样的高并发系统是如何做限流的?
  12. Selenium2+python自动化6-八种元素元素定位(Firebug和firepath)
  13. 研究生数学建模经验分享
  14. Python爬虫之小猪短租房
  15. KGB知识图谱完善保险行业的知识应用体系
  16. samba报错:smbd dead but pid file exists
  17. kotlin开发Android入门篇八Kotlin开发Android的基本使用
  18. 诺丁汉大学高级计算机科学,诺丁汉大学高级计算机科学研究生语言及申请要求-费用-课程设置...
  19. 配置华为路由器的常用命令
  20. #92 Backpack

热门文章

  1. 【C++】(二) 类和对象的定义与使用
  2. 2018全球机器学习技术大会7月27-28日就等你来!
  3. 【ViewPager的学习】一、简单使用
  4. 数学家闯了红灯会怎样?
  5. HTML+CSS+JS实现个人相册登录注册
  6. 在html中点击通讯录,通讯录2.html
  7. 号外号外:谷歌可能退出中国
  8. 解决VMware Taking ownership of this virtual machine failed
  9. bzoj4716: 假摔
  10. Github标星超级牛,免费又好用的Redis客户端工具!