P2872

传送门

首先

题目概括:题目让着求使所有牧场都联通.需要修建多长的路.

显然这是一道最小生成树板子题(推荐初学者做).

那我就说一下kruskal吧.

Kruskal算法是一种用来查找最小生成树的算法,由Joseph Kruskal在1956年发表。

用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪心算法的应用。

和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效。------- 来自于百度百科

一、基本思路

kruskal利用了一种贪心的思想,先把每一条边按照边权排一下序,利用并查集维护每一个点.

跑kruskal的时候先判断两个点是不是在一个集合里边,如果在那就说明不用再去连边了.

然后合并的时候记录边权,在搞一个记录加的边数的计数器.

大家都知道一张图如果有\(n\)个节点,那么最少\(n-1\)条边就可以吧这张图搞联通了.

那么我们就可以等到计数器的计数记到\(n-1\) 的时候停止执行(已经得到正解).

然后因为这\(n-1\)条边把图连成一起,那么显然\(n - m\)条边就可以把图分成m个部分(很好想鸭).例题:P1195

二、代码

for (int i = 1; i <= cnt; i++) {
if (father(edge[i].x) != father(edge[i].y)) {//判断是不是在一个集合中
f++;
unionn(edge[i].x, edge[i].y);//合并
ans += edge[i].dis;//记录总权值
}
if (f == m) break;//如果做完了,那就停下啊.
}

此题代码及思路:

因为有一些边是一开始就有的,那么我们可以吧一开始就有的那些边都赋值成0,然后继续跑kruskal就好了.

因为给出的是坐标,那就先把坐标都存起来,然后把这些坐标依照欧几里得距离两两建边.

欧几里得距离公式:\(\sqrt{((x_{1}-x_{2})*(x_{1}-x_{2}) + (y_{1}-y_{2}) * (y_{1}-y_{2}))}\)

#include <bits/stdc++.h>

#define N 1000010
#define M 2010 using namespace std;
int fath[M], n, m; bool b[M];
double px[M], py[M];
struct node {//结构体存边.
int x, y;
double dis;
}edge[N << 2]; int read() {
int s = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
} int father(int x) {
if (x != fath[x]) fath[x] = father(fath[x]);//求是不是在一个集合里
return fath[x];
} void unionn(int x, int y) {
int fx = father(x), fy = father(y);//合并两个集合
fath[x] = fath[y];
} bool cmp(node p, node q) {
return p.dis < q.dis;//sort用品
} int main() {
n = read(), m = read();
int z = n + m;//原本就有的
for (int i = 1; i <= z; i++) fath[i] = i;
int cnt = 0;
for (int i = 1, x, y; i <= n; i++) {
x = read(), y = read();
px[i] = x, px[i] = y;//因为给出的是坐标,先把坐标存起来.
}
for (int i = 1; i <= n; i++) fath[i] = 1;
for (int i = n + 1, x, y; i <= n + m; i++) {
x = read(), y = read();
px[i] = x, py[i] = y;
}
for (int i = 1; i <= n + m; i++) {
for (int j = i + 1; j <= n + m; j++) {//开始存边
cnt++;
edge[cnt].x = i;
edge[cnt].y = j;
edge[cnt].dis = sqrt((px[i] - px[j]) * (px[i] - px[j]) + (py[i] - py[j]) * (py[i] - py[j]));
}
}
sort(edge + 1, edge + cnt + 1, cmp);//给边排一下序
int f = 0;
double ans = 0;
for (int i = 1; i <= cnt; i++) {//kruskal
if (father(edge[i].x) != father(edge[i].y)) {
f++;
unionn(edge[i].x, edge[i].y);
ans += edge[i].dis;
}
if (f == m) break;
}
printf("%.2lf", ans);
}

最新文章

  1. xamarin UWP自定义圆角按钮
  2. Linux Module
  3. js 对象(Object)
  4. ArcGIS 10.2与CityEngine2013共存的安装
  5. JQuery事件处理的注意事项
  6. java基础学习总结三(jdk7新特性、变量(局部变量和成员变量)、常量以及运算符)
  7. Spreadsheet Calculator 电子表格计算器 (Uva 215)
  8. phpcms 调用全站最新发布数据
  9. js 动态切换视频
  10. 如何更好地理解和使用Github
  11. unity3d 之本地推送
  12. ifram 局部刷新,不刷新父级
  13. 描述: http通讯基础类
  14. Twisted 简介
  15. 兼容 iOS Retina(视网膜显示) 的程序
  16. 下拉加载dropload.js
  17. angularJS DOM element() $compile()
  18. 在ASP.NET Web API和ASP.NET Web MVC中使用Ninject
  19. MongodbUtil
  20. Codeforces Round #431 (Div. 2) C. From Y to Y

热门文章

  1. DELL OptiPlex 7050M黑苹果纪录
  2. 简单实现python调用c#dll动态链接库
  3. Android:Toolbar的图标尺寸问题
  4. Axios 各种请求方式传递参数(非axios api 请求方式)
  5. HTML 注释 和 实体字符
  6. 面试题:什么叫平衡二叉查找树--AVL树
  7. 给WEB DYNPRO 程序创建TCODE
  8. Ansible-目录
  9. MySQL Table--独立表空间
  10. Linux 常用命令(根据自己的理解随时更新)