【海岛帝国系列赛】No.2 海岛帝国:“落汤鸡”市的黑帮危机
50200210海岛帝国:“落汤鸡”市的黑帮危机
【试题描述】
近几天,犯罪分子发现“药师傅”帝国的警力约等于0。(请见YSF的海岛帝国)于是开始猖狂了起来。他们选择了依山靠水(农村?)的“落汤鸡”市。开始抢劫财务,一天内发生了5起抢劫案,9起爆炸案,3起枪击案,12起绑架案!搞得YSF夜不能寐,况且每天还有那么多“怪物”要处理。于是,所有的责任都落在了“落汤鸡”市可怜的市长LTJ上。犯罪分子在LTJ市有了好多好多个窝点。市民开始惊慌起来,背井离乡。“郭同学”TONY由于YSF没还债而拒绝伸出援手。这时,YSF的“购物券”WHT提出了一个建议:请大名鼎鼎的“李易峰”探长来化解危机。于是,没主见的YSF照办了。不过,由于犯罪团伙庞大,作案频繁,数量众多,LTJ调查不清楚有几个犯罪团伙。不过,LYF探长还是搜集到了一些线索。助理YSM提出:强盗的同伙的同伙也是同伙,只有没有关系的才各自为政。请你帮帮可怜的LTJ、YSF、LYF,编一个程序来告诉他们有几个独立的犯罪团伙。
【输入要求】
* 第一行n表示强盗的人数,m表示警方搜集到的m条线索
* 接下来m行,每行两个整数a,b表示强盗a,b是同伙
【输出要求】
* 一个数:表示有几个独立的犯罪团伙
【输入实例】
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
【输出实例】
3
【其他说明】
无
【试题分析】
一看到什么团伙,什么信息这样的词,就一定知道要用神奇的“并查集”了。那我们先来看看:什么是并查集吧!
1. 简述
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。常常在使用中以森林来表示。
需要实现的操作有:合并两个集合,判断两个元素是否属于一个集合。
这里介绍的主要是普通的并查集,很多情况下使用的并查集是需要扩展的,根据使用情况的不同,有很多差别,这里仅仅是最基本的算法。
经典的find函数:
int findset(int x)
{
if(pa[x] != x)
{
int root = findset(pa[x]);
return pa[x] = root;
}
else
{
return x;
}
}
初始化:
void init() //初始化 该函数可以根据具体情况保存和初始化需要的内容
{
for(int i = ; i < MAX_SIZE; i++)
{
pa[i] = i;
}
}
1、Make_Set(x) 把每一个元素初始化为一个集合
初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。
2、Find_Set(x) 查找一个元素所在的集合
查找一个元素所在的集合,其精髓是找到这个元素所在集合的祖先!这个才是并查集判断和合并的最终依据。
判断两个元素是否属于同一集合,只要看他们所在集合的祖先是否相同即可。
合并两个集合,也是使一个集合的祖先成为另一个集合的祖先,具体见示意图
3、Union(x,y) 合并x,y所在的两个集合
合并两个不相交集合操作很简单:
利用Find_Set找到其中两个集合的祖先,将一个集合的祖先指向另一个集合的祖先。如图
并查集的优化
1、Find_Set(x)时 路径压缩
寻找祖先时我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度,有没有办法减小这个复杂度呢?
答案是肯定的,这就是路径压缩,即当我们经过"递推"找到祖先节点后,"回溯"的时候顺便将它的子孙节点都直接指向祖先,这样以后再次Find_Set(x)时复杂度就变成O(1)了,如下图所示;可见,路径压缩方便了以后的查找。
2、Union(x,y)时 按秩合并
即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小。
1
int father[MAX]; /* father[x]表示x的父节点*/
2
int rank[MAX]; /* rank[x]表示x的秩*/
3
4
5
/* 初始化集合*/
6
void Make_Set(int x)
7
{
8
father[x] = x; //根据实际情况指定的父节点可变化
9
rank[x] = 0; //根据实际情况初始化秩也有所变化
10
}
11
12
13
/* 查找x元素所在的集合,回溯时压缩路径*/
14
int Find_Set(int x)
15
{
16
if (x != father[x])
17
{
18
father[x] = Find_Set(father[x]); //这个回溯时的压缩路径是精华
19
}
20
return father[x];
21
}
22
23
24
/*
25
按秩合并x,y所在的集合
26
下面的那个if else结构不是绝对的,具体根据情况变化
27
但是,宗旨是不变的即,按秩合并,实时更新秩。
28
*/
29
void Union(int x, int y)
30
{
31
x = Find_Set(x);
32
y = Find_Set(y);
33
if (x == y) return;
34
if (rank[x] > rank[y])
35
{
36
father[y] = x;
37
}
38
else
39
{
40
if (rank[x] == rank[y])
41
{
42
rank[y]++;
43
}
44
father[x] = y;
45
}
46
}
47
并且传说中的并查集按秩合并:
const int MAXSIZE = ;
int uset[MAXSIZE];
int rank[MAXSIZE]; void makeSet(int size) {
for(int i = ;i < size;i++) uset[i] = i;
for(int i = ;i < size;i++) rank[i] = ;
}
int find(int x) {
if (x != uset[x]) uset[x] = find(uset[x]);
return uset[x];
}
void unionSet(int x, int y) {
if ((x = find(x)) == (y = find(y))) return;
if (rank[x] > rank[y]) uset[y] = x;
else {
uset[x] = y;
if (rank[x] == rank[y]) rank[y]++;
}
}
这题只是并查集的基础,用到了find和merge合并
剩下的就貌似只有sum++了
【代码】
#include<iostream>
using namespace std;
int f[]={},n,m,k,sum=;
void init()
{
int i;
for(i=;i<=n;i++) f[i]=i;
return ;
}
int getf(int v)
{
if(f[v]==v) return v;
else
{
f[v]=getf(f[v]);
return f[v];
}
}
void merge(int v,int u)
{
int t1,t2;
t1=getf(v);
t2=getf(u);
if(t1!=t2) f[t2]=t1;
return ;
}
int main()
{
int i,x,y;
scanf("%d%d",&n,&m);
init();
for(i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
merge(x,y);
}
for(i=;i<=n;i++)
if(f[i]==i) sum++;
printf("%d\n",sum);
}
【海岛帝国系列赛】No.2 海岛帝国:“落汤鸡”市的黑帮危机的更多相关文章
- 【海岛帝国系列赛】No.7 海岛帝国:神圣之日
50237242海岛帝国:神圣之日 [试题描述] 战争持续九个月了.“购物券”WHT的军队还在跟恐怖分子僵持着.WHT和LJX已经向“公务员”告急,情况不宜乐观.YSF为守护帝国决定打开“够累 的”星 ...
- 【海岛帝国系列赛】No.6 海岛帝国:战争前线
50234237海岛帝国:战争前线 [试题描述] 总指挥官WHT出神入化的计谋虽然大有用武之地,但是聪明的恐怖分子们采取了城市核武器防御系统,可以有效地抵制WHT的炸弹.YSF对此头痛不已,因此 召开 ...
- 【海岛帝国系列赛】No.5 海岛帝国:独立之战
50229234海岛帝国:独立之战 [试题描述] 恐怖分子多年来一直如饥似渴地渴求“药师傅”帝国,但是,“里脊肉”BANNIE时刻在守护着这一方水土.从而使帝国日益强大.如今,BANNIE由于在 “牡 ...
- 【海岛帝国系列赛】No.4 海岛帝国:LYF的太空运输站
50212228海岛帝国:LYF的太空运输站 [试题描述] 最近,“购物券”WHT在“药师傅”帝国资源大会上提出了“SSTS”太空运输站计划.由于恐怖分子前些日子刚猖狂完,炸毁高楼无数,YSF不得不执 ...
- 【海岛帝国系列赛】No.3 海岛帝国:运输资源
海岛帝国:运输资源 [试题描述] YSF考虑到“药师傅”帝国现在资源极度不平均,于是,商讨启用南水北调工程.YZM为首席工程师.现在,YSF由于工作紧张,准备军用物资和民用物资.但他要时时关注运输工程 ...
- 【海岛帝国系列赛】No.1 海岛帝国:诞辰之日
50111117海岛帝国:诞辰之日 [试题描述] YSF自从上次“被盗投降”完(带着一大堆债)回去以后,YSF对“海盗”怀念至今,他想要建立一个“药师傅”海岛帝国. 今天,他要像“管理部”那样去探寻 ...
- 帝国cms7.0忘记后台管理账户用户名密码
最近刚登陆以前的网站,但是发现自己的后台管理用户名密码已经忘记,于是到帝国cms论坛里面找了一下解决方案,成功解决问题.特此分享一下解决成功经验. 原帖地址:http://bbs.phome.net/ ...
- Java开发笔记(四)Java帝国的度量衡
秦始皇统一中国之后,实行“书同文,车同轨”,把货币和各种度量衡都统一起来,从而缔造了一个秩序井然的帝国.既然统一度量衡是每个帝国都要做的事情,Java帝国也不例外,对于人生地不熟的初学者来说,只有认识 ...
- DEDEcms和帝国cms的几点比较
前言:最近有很多人问我DEDEcms和帝国cms哪个比较好,我之前用2个都做过站的,所以能够说出它们大体的区别. 声明:我在此说明的是我一贯用的两种建站体统的感受,没有诋毁或者提升哪个系统!两个系统都 ...
随机推荐
- Android开发笔记:SQLite导入导出数据
SQLite是Android中最方便使用的数据库了,现在看下如何快速的在SQLite中导入导出数据. 首先由于是.NET项目转Android,原有数据库使用的是SQLSERVER,由于项目相同部分结构 ...
- ASP.NET页面间数据传递的方法<转>
ASP.NET页面间数据传递的方法 作者: 灰色的天空2 来源: 博客园 发布时间: 2010-10-28 11:06 阅读: 822 次 推荐: 0 原文链接 [收藏] 摘要:本 ...
- Fiddler-002-常用配置修改
日常在应用 Fiddler 进行网络抓包时,有时需要查看服务器的类型或者其他信息,此文主要讲述实际应用中针对 Fiddler 进行的定制化配置,以方便日常的工作学习. 第一:显示服务器的类型和请求域名 ...
- FragmentActivity和Activity的区别
[转载] 直说总结了: 1.fragmentactivity 继承自activity,用来解决android3.0 之前没有fragment的api,所以在使用的时候需要导入support包,同时继承 ...
- 移动端公共css样式
@media screen and ( min-width: 319px){html{ font-size: 100px;}}@media screen and ( min-width: 359px) ...
- SQLPlus Error handle
SQLPlus directive "WHENEVER SQLERROR EXIT 1" will return a specified code when any SQL err ...
- Hibernate中in语句ids
Query query=session.createQuery("from User where id in (:ids)"); query.setParameterList(&q ...
- Docker数据管理
用户在使用Docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据共享,这必然涉及到Docker的数据管理. 容器中管理数据主要有两种方式: ...
- Android系统自带样式(@android:style/)
在AndroidManifest.xml文件的activity中配置 1.android:theme="@android:style/Theme" 默认状态,即如果theme这里不 ...
- C# WebSocket 服务端示例代码 + HTML5客户端示例代码
WebSocket服务端 C#示例代码 using System; using System.Collections.Generic; using System.Linq; using System. ...