不想看模板,想直接看题目的请戳下面目录:

目录:

HDU 1213 How Many Tables【传送门】

HDU 1232 畅通工程 【传送门】

POJ 2236 Wireless Network 【传送门】

POJ 1703 Find them, Catch them 【传送门】


先上模板:

 #define MAXN 根据编号需要
int per[MAXN],rank[MAXN]; void init(int n)
{
int i;
for(i=;i<=n;i++)
{
per[i]=i;rank[i]=
} } int find(int x)
{
if(x==per[x])
return x;
return per[x]=find(per[x]);
} void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return;
if(rank[x]>rank[y])
per[y]=x;
else
{
per[x]=y;
if(rank[x]==rank[y])
rank[y]+=;
}
} bool same(int x,int y)
{
return find(x)==find(y);
}

并查集详解请访问:(通俗易懂解释)

https://blog.csdn.net/lesileqin/article/details/96703143


接下来来看几个例子:

HDU 1213 How Many Tables【传送门】

题目大意:有一个人过生日,请到了他的诸多朋友,但是这些朋友之间有的认识,有的不认识。这个人想尽可能的把相互之间认识的人凑到一张桌子上,不认识的人则去另一张桌子。朋友们互相认识的规则是:比如A认识B,B认识C,那么A,B,C就可以凑到一桌子上。现在问:他的朋友们以这样的规则能凑够几桌。

解题思路:运用并查集,把相互认识的人都联合一下,到最后计算数组中有几个per值等于自身的人就可以了。

 #include<iostream>

 using namespace std;

 int f[];

 void init(int n)
{
for(int i=;i<=n;i++)
f[i]=i;
} int find(int a)
{
while(a!=f[a])
{
a=f[a];
}
return a;
} void Combin(int a,int b)
{
int ta,tb;
ta=find(a);
tb=find(b); if(ta!=tb)
f[ta]=tb;
} int answer(int n)
{
int sum=;
for(int i=;i<=n;i++)
if(f[i]==i)
sum++;
return sum;
} int main()
{ int t;
cin >> t;
while(t--)
{
int n,m;
cin >> n >> m;
init(n);
int a,b;
for(int i=;i<m;i++)
cin >> a >> b,Combin(a,b);
cout << answer(n) << endl ;
} return ;
}

HDU 1232 畅通工程 【传送门】

此处略去题目大意……

解题思路:其实这个题目和上一个题异曲同工,就是变换了一下条件,我们假设村子是上题的朋友,那么路就是朋友们之间的关系,那么两堆朋友之间连线,其实只需要一次就可以了,同样,三堆朋友之间要想相互认识,只需要两个关系就可以了,所以我们很容易可以得出朋友们要想都认识,只需要把朋友堆数 - 1 就可以了。

代码只需要将上题的输出结果-1即可 ,不再贴出。


POJ 2236 Wireless Network 【传送门】

题目大意:一片废弃的地方,ACM协会正在进行救援,可是所有电脑的通信设施都被破坏了,被修复好的电脑的信号传输距离只有d米,现在给出所有电脑的坐标,然后给出指令S与O,S后跟两个数字代表两个电脑的编号,询问这两台电脑是否能通信,如果能则输出SUCCESS,否则输出FALL;O后跟一个编号,代表修好一定电脑。

解题思路:此题运用并查集,在修复好一台电脑之后遍历所有修好的电脑,如果两点间距离小于d米,则连通两个点;遇到S的时候只需要判断是否连通即可。

 #include<iostream>
#include<cmath>
using namespace std;
#define MAXN 1005 //坐标
struct pos{
int x,y;
int par_id; //父辈id
int rank; //树的高度
}; struct pos par[MAXN]; //记录父亲
bool isok[MAXN]; //是否被修复成功 float Distance(struct pos a,struct pos b)
{
float dis=sqrt(fabs(a.x-b.x)*fabs(a.x-b.x)+fabs(a.y-b.y)*fabs(a.y-b.y));
return dis;
} void init(int n)
{
for(int i=;i<=n;i++)
{
par[i].par_id=i;
par[i].rank=;
isok[i]=false;
}
} //查树根
int find(int x)
{
if(par[x].par_id==x)
return x;
else
return par[x].par_id=find(par[x].par_id);
} //合并
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return;
if(par[x].rank<par[y].rank)
par[x].par_id=y;
else{
par[y].par_id=x;
if(par[x].rank==par[y].rank)
par[x].rank++;
}
} //判断x和y是不是同一个集合
bool same(int x,int y)
{
return find(x)==find(y);
} int main()
{
int N,d;
char c;
cin >> N >> d;
init(N);
for(int i=;i<=N;i++)
{
int x,y;
cin >> x >> y;
par[i].x=x;
par[i].y=y;
} while(cin >> c)
{
int p,q;
if(c=='O')
{
cin >> p;
isok[p]=true;
for(int i=;i<=N;i++)
{
if(isok[i]==true&&i!=p)
{
struct pos a,b;
a.x=par[i].x;
a.y=par[i].y;
a.par_id=par[i].par_id;
b.x=par[p].x;
b.y=par[p].y;
b.par_id=par[p].par_id;
if(Distance(a,b)<=d)
{
// cout << Distance(a,b) << endl;
unite(p,i);
} }
}
}
else if(c=='S')
{
cin >> p >> q;
if(same(p,q))
cout << "SUCCESS\n";
else
cout << "FAIL\n";
}
// for(int i=1;i<=N;i++)
// cout << par[i].par_id << " ";
// cout << endl;
}
return ;
}

POJ 1703 Find them, Catch them 【传送门】

题目大意:有两个帮派,警察现在抓住了N个罪犯,输入字母A或D,后面跟着两个罪犯的编号。如果字符是A,则代表这一次询问:如果不是一个帮派,则输出“In different gangs.”;是一个帮派输出"In the same gang.";否则输出“Not sure yet.”。如果是字符D,那就代表着后面的两个编号不属于一个帮派!

解题思路:需要一个标记数组vis,用来标记两个罪犯(a,b)不属于同一个帮派,如果标记数组两个罪犯都为0则代表不确定是哪个帮派,并且让vis[a]=b,vis[b]=a;如果vis[a]==0&&vis[b]!=0,则让vis[b]=a,并且连通a,vis[b];如果vis[b]==0&&vis[a]!=0,则让vis[a]=b,并且连通b,vis[a];最后一种情况是a与b的标记数组都不为0,那么连2019-07-21通a,vis[b],连通b,vis[a]最后判断即可。

 //#include<iostream>
//using namespace std;
#include<stdio.h>
#define MAXN 100010 int per[MAXN],rank[MAXN],vis[MAXN]; void init(int n)
{
int i;
for(i=;i<=n;i++)
{
per[i]=i;rank[i]=;vis[i]=;
} } int find(int x)
{
if(x==per[x])
return x;
return per[x]=find(per[x]);
} void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return;
if(rank[x]>rank[y])
per[y]=x;
else
{
per[x]=y;
if(rank[x]==rank[y])
rank[y]+=;
}
} int Same(int x,int y)
{
if(find(x)==find(y))
return ; } int main()
{
// ios::sync_with_stdio(false);
int t;
scanf("%d",&t);
// cin >> t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
// cin >> n >> m;
init(n);
while(m--)
{
int a,b;
char c[];
scanf("%s",c);
//getchar();
scanf("%d%d",&a,&b);
//cin >> c >> a >> b;
//联立
//printf("%c\n",c);
if(c[]=='D')
{
if(vis[a]==&&vis[b]==)
{
vis[a]=b;
vis[b]=a;
}
else if(vis[a]==)
{
vis[a]=b;
unite(a,vis[b]);
}
else if(vis[b]==)
{
vis[b]=a;
unite(b,vis[a]);
}
else{
unite(a,vis[b]);
unite(b,vis[a]);
}
}
else{
if(Same(a,b))
printf("In the same gang.\n");
//cout << "In the same gang.\n";
else if(Same(a,vis[b]))
//cout << "In different gangs.\n";
printf("In different gangs.\n");
else
printf("Not sure yet.\n");
//cout << "Not sure yet.\n";
}
}
} return ;
}

【并查集】模板 + 【HDU 1213、HDU 1232、POJ 2236、POJ 1703】例题详解的更多相关文章

  1. HDU 1213 How Many Tables(并查集模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1213 题意: 这个问题的一个重要规则是,如果我告诉你A知道B,B知道C,这意味着A,B,C知道对方,所以他们可以 ...

  2. 【2018寒假集训Day 8】【并查集】并查集模板

    Luogu并查集模板题 #include<cstdio> using namespace std; int z,x,y,n,m,father[10001]; int getfather(i ...

  3. POJ-图论-并查集模板

    POJ-图论-并查集模板 1.init:把每一个元素初始化为一个集合,初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变). void init() { for ...

  4. 【并查集模板】 【洛谷P2978】 【USACO10JAN】下午茶时间

    P2978 [USACO10JAN]下午茶时间Tea Time 题目描述 N (1 <= N <= 1000) cows, conveniently numbered 1..N all a ...

  5. 【并查集模板】并查集模板 luogu-3367

    题目描述 简单的并查集模板 输入描述 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1时,将Xi与Yi所在的集合合并 当Zi=2时,输出 ...

  6. Memcached集群/分布式/高可用 及 Magent缓存代理搭建过程 详解

    当网站访问量达到一定时,如何做Memcached集群,又如何高可用,是接下来要讨论的问题. 有这么一段文字来描述“Memcached集群” Memcached如何处理容错的? 不处理!:) 在memc ...

  7. Android查缺补漏(IPC篇)-- 款进程通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  8. Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  9. HDU 1213 - How Many Tables - [并查集模板题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1213 Today is Ignatius' birthday. He invites a lot of ...

随机推荐

  1. 使用百度网盘+Git,把版本控制托管到云端,附精彩评论

    http://www.cnblogs.com/vajoy/p/3929675.html 我试过多个这种双向同步的网盘,在网络状况不好.系统卡顿以及某些程序BUG的情况下,同步会有错乱现象,尤其是多个电 ...

  2. Delphi 中 断言 Assert 用法

    procedure Assert(expr : Boolean [; const msg: string]); 用法:   Assert(表达式,[显示信息]); 如果为假, assert会产生一个E ...

  3. 新玩法,CentOS7中LVM通过扩展逻辑卷扩展swap空间

    在我们日常运维工作中,偶尔也会遇到需要扩展swap空间的操作.扩展swap空间的方法很多,现在让我们一起来探讨一下,在LVM下扩展swap空间的方法. 1.查看一下卷组,是否还有空闲空间能用于扩展sw ...

  4. 使用C++还是QML(QML容易使用和维护,效果好)

    本质上,Qt 是一个C++类库.在引入 QML 以前,所有的开发都是基于 C++ 的,但到了 Qt 5,QML 和 Qt Quick 成为了 Qt 的核心之一,导致很多初学者在犹豫是否还需要学习 C+ ...

  5. 多线程基础理论--C#

    1.主线程 进程创建时,默认创建一个线程,这个线程就是主线程.主线程是产生其他子线程的线程,同时,主线程必须是最后一个结束执行的线程,它完成各种关闭其他子线程的操作.尽管主线程是程序开始时自动创建的, ...

  6. 如何让你的Sublime和Codeblocks支持C++11

    闲来没事看了一下C++11,比起C++0x多了很多新功能,像auto变量,智能指针等,g++4.7以上版本也提供了对C++11的支持,但是,如何在你的编辑器上执行C++11代码呢? 刚开始以为用法和以 ...

  7. 测试链接服务器sql 语句

    sp_addlinkedsrvlogin 创建或更新本地 Microsoft® SQL Server™ 实例上的登录与链接服务器上远程登录之间的映射. 语法 sp_addlinkedsrvlogin ...

  8. SYN2306B型 GPS北斗双模授时板

    SYN2306B型 GPS北斗双模授时板 产品概述 SYN2306B型GPS北斗双模授时板是由西安同步电子科技有限公司精心设计.自行研发生产的一款双模授时板卡,接收北斗或者GPS北斗混合授时卫星信号, ...

  9. GStreamer基础教程03 - 媒体类型与Pad

    摘要 在上一篇文章中,我们介绍了如何将多个element连接起来构造一个pipline,进行数据传输.那么GStreamer是通过何种方式保证element之间能正常的进行数据传输?今天就将介绍GSt ...

  10. org.springframework.beans.factory.BeanCreationException: Could not autowire field org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [com.xxxx.service.sys.impl.ProcEn

    七月 01, 2019 4:34:20 下午 org.apache.catalina.core.StandardContext listenerStart .....org.springframewo ...