首页 > 其他分享 >P1536 村村通(并查集)

P1536 村村通(并查集)

时间:2024-01-24 20:12:19浏览次数:25  
标签:P1536 int 查集 城镇 道路 include find 村村通

村村通

题目描述

某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?

输入格式

输入包含若干组测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目 n 和道路数目 m;随后的 m 行对应 m 条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从 1到 n 编号。

注意:两个城市间可以有多条道路相通。

在输入数据的最后,为一行一个整数 0,代表测试数据的结尾。

输出格式

对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。

样例 #1

样例输入 #1

4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

样例输出 #1

1
0
2
998

提示

数据规模与约定

对于 100% 的数据,保证 1 ≤ n < 1000

思路

  1. 计算并查集中的“祖宗”一共有几个,村村通也就是把这些祖宗连接在一起就可以实现题目要求,祖宗连接的最少路径数是n-1

  2. 并查集实现

    其实并查集很好理解总而言之就是找祖宗,如果退出递归的条件就是找到自己的祖宗是自己。合并路径只是多了一步记忆的过程可以省点时间

    int find(int x){
    	if(x==f[x])return x;
    	else{
    		return f[x]=find(f[x]);//本题的数据量不合并路径应该也能过
    	}
    }
    void merge(int i,int j){
    	f[find(i)]=find(j);
    }
    

AC Code

// Problem: 
//     P1536 村村通
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1536
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
//#include<cstdio>
#include<set>
#define ll long long 
#define endl '\n'
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>(b);i--)
#define N 1010 //1e6+100 
 
using namespace std;
int n,m;
int f[N];
set<int>s;
void Mymemset(int lmt){
	for(int i=1;i<=lmt;i++) f[i]=i;
}
int find(int x){
	if(x==f[x])return x;
	else{
		return f[x]=find(f[x]);
	}
}
void merge(int i,int j){
	f[find(i)]=find(j);
}
void solve(){
	Mymemset(n);
	s.clear();
	cin>>m;
	int x,y;
	while(m--){
		cin>>x>>y;
		merge(x,y);
	}
	for(int i=1;i<=n;i++){
		s.insert(find(i));
	}
	cout<<s.size()-1<<endl;
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	while(1){
		cin>>n;
		if(n==0)return 0;
		else solve();
	}
	return 0; 
} 

标签:P1536,int,查集,城镇,道路,include,find,村村通
From: https://www.cnblogs.com/Illuminated/p/17985755

相关文章

  • CF-1184-E3-最小生成树+倍增+并查集
    1184-E3题目大意给定一个\(n\)个点,\(m\)条边的无向图,边带权。对于每条边,你需要找到最大值\(x\),使得把这条边的权值修改为\(x\)后能够出现在最小生成树上。Solution先把整个图的最小生成树弄出来,然后将边分为树边以及非树边来考虑:非树边:对于一个非树边连接了\(x\)和\(y\)的......
  • 并查集与反集——P1892团伙
    并查集并查集如其名,合并与查找查找intfind(intkey){ if(fa[key]==key)returnkey; elsereturnfa[key]=find(fa[key]);}合并voidunite(intx,inty){ intfax=find(x); intfay=find(y); fa[fax]=fay; return;}反集处理并查集合并问题的敌对/......
  • 并查集
    并查集是一种集合结构,用来处理集合的合并和查询问题。主要有两个函数:合并和查询合并函数表示合并两个不同的集合查询表示当前元素属于那个集合逻辑结构是单链表的结构,每个节点向上指向一个属于的集合的代表元素,这个集合的代表元素的next指向它自己成环,表示这个集合的代表元素......
  • CF-292-D-并查集
    292-D题目大意给定一张无向图,由\(n\)个顶点\(m\)条边。有\(q\)次询问,每次询问将\([l,r]\)的边删去,问图中有多少连通分量。Solution涉及连通分量,尝试应用并查集解决。记录一个前缀并查集\(pre[i]\),表示前\(i\)条边连通后的图;和一个后缀并查集\(suf[i]\),表示后\(m-i\)条边连通......
  • CF-915-F-并查集
    915-F题目大意给定一棵\(n\)个节点的树,节点带权,设函数\(I(x,y)\)等于点\(x\)到点\(y\)的路径上最大的点权与最小的点权之差。求:\[\sum_{i=1}^{n}\sum_{j=i}^{n}I(i,j)\]Solution令函数\(F(i,j)\)等于点\(x\)到点\(y\)的路径上最大的点权,函数\(G(i,j)\)等于点\(x\)到点\(y\)......
  • 并查集综合
    种类并查集关押罪犯经典种类并查集。考虑要想使最后的结果尽可能小,必须按照怨气值大小将每组关系排序,从大到小依次将罪犯放入监狱。对于放的过程,用并查集维护。由于我们已经将怨气值大小排序,所以对于一组\(a\)与\(b\)的矛盾,将\(a\)与\(b\)不放在同一个监狱一定是最优......
  • 并查集
    并查集基础并查集(\(\sfDisjoint\Set\Union\),\(\sfDSU\))是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。初始化:初始化时每个节点均为一个集合,因此根节点初始化为自己。for(inti=1;i<=n;i++)fa[i]......
  • abc097d<并查集,排列>
    题目D-Equals给出\(1\simn\)的排列p,给出\(m\)种对换\((p_i,p_j)\),在这\(m\)种对换中任选操作,对原排列对换任意多次。求能够实现的\(p_i=i\)的最大个数为多少?思路将m中对换中能够相互关联的位置归为一组,这组位置之间可通过对换操作实现任意顺序;因而对于一组内的数据,是......
  • 并查集基础 &打击罪犯
    并查集基础真的很基础题目描述:Description某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度唯一由集团内的......
  • 并查集
    并查集并查集是一种采用树形结构存储的集合,可以高效的查找两个元素是否在一个集合当中以及合并两个集合。这里的树形结构并非仅指二叉树,而是一个节点可以有多个孩子。对于一个并查集的节点,它可以有两个元素,一个存储该节点的数据,另一个用来指向其父节点。当然当我们所存储的元......