如果对最小生成树的Kruskal有了解可以只看黄色字体部分,斜体字方便小白加强理解,能懂的省时间的可以不看。

Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路。道路被用来连接N个牧场,牧场被连续地编号为1到N。每一个牧场都是一个奶牛的家。FJ计划除去P条道路中尽可能多的道路,但是还要保持牧场之间 的连通性。你首先要决定那些道路是需要保留的N-1条道路。第j条双向道路连接了牧场Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N; Sj != Ej),而且走完它需要Lj的时间。没有两个牧场是被一条以上的道路所连接(最后没有形成环)。奶牛们非常伤心,因为她们的交通系统被削减了。你需要到每一个奶牛的住处去安慰她们。每次你到达第i个牧场的时候(即使你已经到过),你必须花去Ci的时间和奶牛交谈。你每个晚上都会在同一个牧场(这是供你选择的)过夜,直到奶牛们都从悲伤中缓过神来。在早上起来和晚上回去睡觉的时候,你都需要和在你睡觉的牧场的奶牛交谈一次。这样你才能完成你的交谈任务。假设Farmer John采纳了你的建议,请计算出使所有奶牛都被安慰的最少时间。

输入格式 
第1行包含两个整数N和P。

接下来N行,每行包含一个整数Ci。

接下来P行,每行包含三个整数Sj, Ej和Lj。

输出格式 
输出一个整数, 所需要的总时间(包含和在你所在的牧场的奶牛的两次谈话时间)。 
样例输入 

5 7
10
10
20
6
30
1 2 5
2 3 5
2 4 12
3 4 17
2 5 15
3 5 6 

样例输出 

176

数据规模与约定 
5 <= N <= 10000,N-1 <= P <= 100000,0 <= Lj <= 1000,1 <= Ci <= 1,000.

拿样例来说:

这里样例输入的初始道路p是7,最后数据只给了6组,应该还有一组是4 5 12。

5个牧场,和奶牛交谈的时间当作点权(图中黑色数字),通过连接牧场之间的道路时间当作边权(图中蓝色数字)。

最小生成树的Kruskal算法是先忽略所有道路的存在,然后以边权从小到大排列来选择道路。因此可以通过对边的筛选来确定最终要选择的N-1条道路。

这里的筛选要满足边的两个端点不在同一个连通块中。连通块:连通块中的牧场可以通过一条或一条以上的道路自由通行。

    比如1号牧场直接到达2号牧场,则1、 2号牧场是一个连通块;1号牧场通过2号牧场再到达4号牧场,则1、 2、 4号牧场是一个连通块。一开始我们忽略所有边,所以N个牧场就是N个连通块。

如何知道两个端点是否在一个连通块中呢?可以使用并查集数组 father[n]。并查集:通过判断两个端点的根结点数字是否相同来确定是否在一个连通块。

    比如1、 2号牧场一开始不是同一个连通块,它们的根结点数字分别是自己的牧场编号1、 2,由于根结点数字不同,所以得知这两个牧场不连通。当选择1、 2号之间的道路后需要让他们成为连通块,这时只需要修改2的根结点为1就行了。

由于每次经过某牧场都要花Ci时间(点权)和奶牛交谈,所以可以得知每经过一条边需要花的时间是边权+两个端点的点权。又因为最后保留的N-1条道路没有形成环,且走完所有牧场后需要回到你选择的某个牧场睡觉,因此可以保证每条边都会被走2次(可以自己画多几个图试试看)。为了方便计算,我们将所有边权更新为:边权 = 端点1的点权 + 端点2的点权 + 边权 × 2(见下图),这样做最后只需用边权相加即可得到最短时间。

    这里先给出样例中算法得出的路线供理解:4→5→4→2→1→2→3→2→4,经过的道路有4条,拿边权(蓝色数字)来计算,最终共花30+40+40+60=170的时间(注意不是最终结果),睡觉的牧场是4号。

PS:有人可能疑问两个边权60,拿哪一个相加,注意算法此时已经得出3、 4号牧场是一个连通块了(因为前面选择边权40的道路时已经将3号加入连通块中),而5号未连通,所以选择的是4、 5号之间的60。

最后需要事先选择一个睡觉的牧场(起点)。由于已经解决全部计算问题,包括最终回到睡觉的牧场,所以只需决定最一开始在哪个牧场空降,当然是选择点权最小的牧场啦,所以样例中选择的是4号。

    代码补充说明:sort()函数:对给定区间的元素(e, e+m)进行排序,cmp是排序准则。

#include<iostream>
#include<algorithm>
using namespace std;struct edge{int p1, p2; //边的两个端点 int cost;  //边权
}e[100010];bool cmp(edge a, edge b){    //用排序函数将数组e按边权从小到大排序 return a.cost < b.cost;
}int father[10010];      //并查集数组
int findFather(int x){  //判断两个端点根结点是否相同return father[x] == x? x: father[x] = findFather(father[x]);
} int kruskal(int n, int m){int ans = 0, edgeNum = 0;for(int i = 0; i < n; i++)  father[i] = i;    //并查集初始化,每个牧场是独立的连通块sort(e, e+m, cmp);      for(int i = 0; i < m; i++){int fa_p1 = findFather(e[i].p1);  //获取端点1的根结点int fa_p2 = findFather(e[i].p2);  //获取端点2的根结点if(fa_p1 != fa_p2){ father[fa_p2] = fa_p1;   //合并连通块(修改端点p2的根结点使其与p1的一致)ans += e[i].cost;edgeNum++;if(edgeNum == n-1) break; //边数=顶点数-1时结束循环 }}return ans;
}int main()
{int n, m;cin >> n >> m;int c[n], st = 1010;    //点权,起点 for(int i = 0; i < n; i++){cin >> c[i];if(c[i] < st)st = c[i];    //确保起点点权最小        }for(int i = 0; i < m; i++){cin >> e[i].p1 >> e[i].p2 >> e[i].cost;e[i].cost = c[e[i].p1-1] + c[e[i].p2-1] + e[i].cost * 2;}int ans = kruskal(n, m);cout << st + ans << endl;return 0;
}

安慰奶牛 C++ kruskal相关推荐

  1. 安慰奶牛 问题描述 Farmer John变得非常懒,他不想再继续维

    package ALGO;/*安慰奶牛 时间限制:1.0s 内存限制:256.0MB问题描述Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续 ...

  2. 蓝桥杯-安慰奶牛(java)

    算法训练 安慰奶牛   时间限制:1.0s   内存限制:256.0MB 问题描述 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续地编号为 ...

  3. bzoj1232[Usaco2008Nov]安慰奶牛cheer*

    bzoj1232[Usaco2008Nov]安慰奶牛cheer 题意: 给出n个节点的带权图,第i个节点ci.现在你要在这个图中选出一棵树和一个起点,然后你要从起点出发到达所有的节点(不能跳点)再回到 ...

  4. P2916 [USACO08NOV]安慰奶牛Cheering up the Cow

    题目 P2916 [USACO08NOV]安慰奶牛Cheering up the Cow 分析 这题开始不是很懂它的意思,看了题解才懂的.举个例子:有一条边 a->b 那么假定我们从a点出发再回 ...

  5. 1232: [Usaco2008Nov]安慰奶牛cheer

    1232: [Usaco2008Nov]安慰奶牛cheer Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 612  Solved: 431 [Sub ...

  6. C语言题目奶牛牧场,C语言算法训练:安慰奶牛

    C语言算法训练:安慰奶牛 导语:FJ变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续地编号为1到N.下面我们来看看C语言算法训练:安慰奶牛. 每一个牧场都是一个奶 ...

  7. 安慰奶牛 (算法训练)

    算法训练 安慰奶牛   时间限制:1.0s   内存限制:256.0MB        问题描述 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧 ...

  8. 讲解 算法训练 安慰奶牛

    首先谈谈这道题的基本思路吧,题目中谈到要将P条道路尽可能的去减少,并保证个点之间是可达的,同时要求其最小时间. 很明显的去告诉我们,用最小生成树算法. 最小生成树算法有两种, 1.克鲁斯卡尔算法 2. ...

  9. 最小生成树——安慰奶牛(蓝桥杯试题集)

    *对prim算法.Kruskal算法不是很理解的请移步 http://blog.csdn.net/sm9sun/article/details/53256232  //并查集 http://blog. ...

最新文章

  1. 获取 一个文件 在沙盒Library/Caches/ 目录下的路径
  2. 35岁以前成功的12条黄金法则
  3. Laravel查询搜索函数集合:find  first  firstWhere firstOr findOrFail firstOrFail firstOrNew firstOrCreate
  4. SQL基础【五、Where】
  5. commons-lang3工具类学习(二)
  6. Apache专用笔记贴
  7. jzoj3461-小麦亩产一千八【斐波那契数列】
  8. 【LeetCode笔记】1143. 最长公共子序列(Java、动态规划、字符串)
  9. [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  10. Python中的mkdir -p功能[重复]
  11. bootstrap的表单验证 vue_分享几个基于Vue的UI库和开源项目
  12. sap 分摊分配不产生会计凭证的原因_会计凭证的实际分类及凭证管理应用
  13. jqueryui时间插件_jQueryUI菜单插件教程示例
  14. Java编程:动态规划
  15. java实现https请求单向认证、双向认证
  16. c语言二级java难吗_计算机二级考JAVA还是C?
  17. 手机H5-调用百度地图导航
  18. CMD命令查看WiFi密码
  19. vim 打开php 回车没了,设置 - VIM在Fi结束时禁用自动换行
  20. ACM暑假集训总结(2014年夏)

热门文章

  1. 好书整理(to be continued)
  2. 输入两个正整数 m 和 k,其中1 < m < 100000,1 < k < 5 ,判断 m 能否被19整除,且恰好含有k个3,如果满足条件,则输出YES,否则,输出NO。
  3. Linux-Samba文件共享服务
  4. 基于kalman滤波的磨损预测算法matlab仿真
  5. layui内置模块(layer弹出层)
  6. 国外ERP项目实施“误”在哪?(转)
  7. 罗振宇 知识就是力量之如何成为一个受欢迎的人
  8. “三色鸽杯”南阳市第四届十大新闻人物揭晓
  9. Acwing 104. 货仓选址 (数学题,绝对值不等式)
  10. 打印当前页面指定元素中的内容