并查集与最小生成树Kruskal算法
一、什么是并查集
在计算机科学中,并查集是一种树型的数据结构,用于处理一些不交集的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个用于次数据结构的操作:
- Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
- Union:将两个子集合并成一个集合。
二、主要操作
- 初始化:把每个点所在的集合初始化为其自身。
for(int i=1;i<=n;i++)
f[i]=i;
- 查找:查找元素所在的集合,即根节点。
int find(int x)
{
while(f[x]!=x)
x=f[x];
return x;
}
- 合并:将两个元素所在的集合合并为一个集合。
void Union(int x1,int x2)
{
int t1=find(x1);
int t2=find(x2);
if(t1!=t2)
f[t2]=t1;
}
三、优化
上面的代码看似简洁,但是每一次find操作的时间复杂度为O(H),H为树的高度,由于我们没有对树做特殊处理,所以树的不断合并可能会使树严重不平衡,最坏情况每个节点都只有一个子节点。
所以在find函数里采用路径压缩。
int find(int x) //查找x元素所在的集合,回溯时压缩路径
{
if (x != f[x])
{
f[x] = find(f[x]);
//从x结点搜索到祖先结点所经过的结点都指向该祖先结点
}
return f[x];
}
四、模板题
#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[10002];
int find(int x)
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
void Union(int x1,int x2)
{
int t1=find(x1);
int t2=find(x2);
if(t1!=t2) //祖先不一样
f[t2]=t1; //把t2的祖先变为x1的祖先t1
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=0;i<m;i++)
{
int z,x,y;
cin>>z>>x>>y;
if(z==1)
Union(x,y);
else
{
if(find(x)!=find(y))cout<<"N"<<endl;
else cout<<"Y"<<endl;
}
}
return 0;
}
五、最小生成树
一个有n个结点的连通图的生成树是原图的极小联通子图,期包含原图的所有n个结点,且有保持图连通的最少边。
最小生成树其实就是最小权重生成树的简称。
Kruskal算法
- 将图的所有边按照权值从小到大排序
- 遍历所有排好序的边,若构不成回路,则将该边加入到集合中
- 直到找出n-1条边
#include<bits/stdc++.h>
using namespace std;
int n,m;
int s,maxm;
int p[100002];
struct node{
int u;
int v;
int c;
}info[100002];
bool cmp(node x1,node x2)
{
if(x1.c!=x2.c)return x1.c<x2.c;
else if(x1.u!=x2.u) return x1.u<x2.u;
else return x1.v<x2.v;
}
int find(int x) //查找x元素所在的集合,回溯时压缩路径
{
if (x!=p[x])
{
p[x]=find(p[x]);
}
return p[x];
}
void bcj(int x1,int x2)//把x2并入x1的集合
{
int t1,t2;//存储祖先节点
t1=find(x1);
t2=find(x2);
if(t1!=t2)p[t2]=t1;
}
int main()
{
cin>>n>>m;//n就是顶点数,m是边数
for(int i=1;i<=n;i++)
{
p[i]=i;
}
for(int i=0;i<m;i++)
{
cin>>info[i].u>>info[i].v>>info[i].c;
}
sort(info,info+m,cmp);
for(int i=0;i<m;i++)//遍历所有的边
{
if(find(info[i].u)!=find(info[i].v))
{
bcj(info[i].u,info[i].v);//把v并入u的集合
maxm=max(maxm,info[i].c);
}
}
cout<<n-1<<" "<<maxm;
return 0;
}
并查集与最小生成树Kruskal算法的更多相关文章
- hdu 1233(还是畅通project)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)
还是畅通project Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- POJ-2421Constructing Roads,又是最小生成树,和第八届河南省赛的引水工程惊人的相似,并查集与最小生成树的灵活与能用,水过~~~
Constructing Roads Time Limit: 2000MS Memory Limit: 65536K Description There are N v ...
- 【转】最小生成树——Kruskal算法
[转]最小生成树--Kruskal算法 标签(空格分隔): 算法 本文是转载,原文在最小生成树-Prim算法和Kruskal算法,因为复试的时候只用到Kruskal算法即可,故这里不再涉及Prim算法 ...
- 模板——最小生成树kruskal算法+并查集数据结构
并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...
- POJ 3723 Conscription (Kruskal并查集求最小生成树)
Conscription Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14661 Accepted: 5102 Des ...
- 关于最小生成树(并查集)prime和kruskal
适合对并查集有一定理解的人. 新手可能看不懂吧.... 并查集简单点说就是将相关的2个数字联系起来 比如 房子 1 2 3 4 5 6 ...
- 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数
题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...
- 最小生成树——kruskal算法
kruskal和prim都是解决最小生成树问题,都是选取最小边,但kruskal是通过对所有边按从小到大的顺序排过一次序之后,配合并查集实现的.我们取出一条边,判断如果它的始点和终点属于同一棵树,那么 ...
- 最小生成树 kruskal算法&prim算法
(先更新到这,后面有时间再补,嘤嘤嘤) 今天给大家简单的讲一下最小生成树的问题吧!(ps:本人目前还比较菜,所以最小生成树最后的结果只能输出最小的权值,不能打印最小生成树的路径) 本Tianc在刚学的 ...
随机推荐
- theme-sodareload sublime编辑器主题插件还不错,不是语法高亮
theme-sodareload sublime编辑器主题还不错,不是语法高亮
- html与HTML5的区别
文档的类型声明不同 html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.or ...
- WebService操作
webservice是一种服务器通信技术,封装了socket.
- sql server if exists用法
if exists用法 if exists 判断表中的内容是否存在 IF EXISTS(SELECT FROM proprice_sheet WHERE vndcode = @vndc ...
- PAT TOP 1005 Programming Pattern (35 分)哈希做法
1005 Programming Pattern (35 分) Programmers often have a preference among program constructs. For ex ...
- 打造简单OS-总目录
1-汇编写入引导区,虚拟机启动步骤 (了解即可) 2-开机BIOS初始化与MBR操作系统引导详解 (了解即可) 3-MBR引导区转移加载简单程序(突破512限制)(了解即可) 4-loader硬盘加载 ...
- [bzoj 4887] [Tjoi2017]可乐
传送门 Description 加里敦星球的人们特别喜欢喝可乐.因而,他们的敌对星球研发出了一个可乐机器人,并且 放在了加里敦星球的1号城市上.这个可乐机器人有三种行为:停在原地,去下一个相邻的 城市 ...
- CF1174D Ehab and the Expected XOR Problem(二进制)
做法 求出答案序列的异或前缀和\(sum_i\),\([l,r]\)子段异或和可表示为\(sum_r\bigoplus sum_{l-1}\) 故转换问题为,填\(sum\)数组,数组内的元素不为\( ...
- SCHED_FIFO与SCHED_OTHER调度机制
疑问 两个线程分别有不同的调度策略,一个SCHED_FIFO,一个SCHED_OTHER,按照之前的理解,SCHED_FIFO实时线程一定会占用CPU一直运行,导致SCHED_OTHER的普通线程得不 ...
- OpenResty之ngx.shared.DICT
参考链接: resty.core.shdict ngx_shared.DICT 源码正文: dict.lua 部分源码如下: local ffi = require 'ffi' local base ...