首页 > 其他分享 >[并查集] 题单刷题摘要

[并查集] 题单刷题摘要

时间:2023-07-31 22:14:39浏览次数:45  
标签:单刷题 查集 fa int 摘要 农场 vis 集合 find

题单

1. P6121 [USACO16OPEN] Closing the Farm G

P3144 [USACO16OPEN] Closing the Farm S(逊版)

思路 \(\scr{Solution}\)

每一时刻关闭农场,求是否全联通。也就是维护将单个集合分成多个集合。

很容易想到爆搜算法,用 vector 邻接表建图,每次跑完图就将当前点的连边关系删去。复杂度 \(O(n^2)\)

只能拿 10pts ,居然有 WA qwq

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 3e3 + 10;
int n, m;
bool vis[N];
vector<int> g[N];

void dfs(int fa, int x)
{
	for (int i = 0; i < g[x].size(); i ++)
	{
		int y = g[x][i];
		if (y == fa || vis[y]) continue;
		vis[y] = true;
		dfs(x, y);
	}
}

void cut(int x)
{
	for (int i = 0; i <g[x].size(); i ++)
		g[x][i] = -1;
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i ++)
	{
		int x, y;
		cin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	while (n --)
	{
		memset(vis, false, sizeof(vis));
		int x;
		cin >> x;
		vis[x] = true;
		dfs(0, x);
		bool flag = false;
		for (int i = 1; i <= n; i ++)
			if (!vis[i])
			{
				flag = true;
				break;
			}
		cout << (flag ? "NO" : "YES") << '\n';
		cut(x);
	}
	
	return 0;
}

正着搜不好优化,考虑倒过来思考。

即一开始所有农场都是关闭的,从后往前,判断每一时刻打开一个农场,对应正着想的当前状态下该农场还未关闭。

而正着想是判断当前状态下是否因关闭该农场而被分成了多个集合。

那倒着想就是打开多个农场,判断是否有多个集合(连通块)!

这不就是并查集了吗 ......

每次打开一个农场,默认多了一个集合,再通过图遍历直接相连的点是否打开了,打开了但又不在同一集合里就用并查集合并,同时抹去该单点集合。

每次操作完后就留下了当前状态下打开了的相连农场的集合数量。 done.

#include<bits/stdc++.h>
using namespace std;
const int N =  2e5 + 10;
int n, m, a[N], fa[N], ans[N];
bool vis[N];
vector<int> g[N];

int find(int x)
{
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void merge(int x, int y)
{
	fa[find(x)] = find(y);
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i ++)
	{
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for (int i = 1; i <= n; i ++) cin >> a[i];
	for (int i = 1; i <= n; i ++) fa[i] = i;
	int sum = 0;
	for (int i = n; i >= 1; i --)
	{
		sum ++;
		int k = a[i];
		vis[k] = true;
		for (int j = 0; j < g[k].size(); j ++)
		{
			int l = g[k][j];
			if (find(k) != find(l) && vis[l])
			{
				merge(k, l);
				sum --;
			}
		}
		ans[i] = sum;
	}
	for (int i = 1; i <= n; i ++)
		cout << (ans[i] == 1 ? "YES" : "NO") << '\n';
		
 	return 0;
}

总结 \(\scr{Summary}\)

  1. 有些题目正着想好做但常常不够优,所以当发现正着想超时时可以试着倒着思考;
  2. 一些分割性的问题可以转化为联通性的问题来做,从而考虑并查集;

标签:单刷题,查集,fa,int,摘要,农场,vis,集合,find
From: https://www.cnblogs.com/hi-zwjoey/p/17594589.html

相关文章

  • luogu P3733 [HAOI2017] 八纵八横 题解【线段树分治+线性基+可撤销并查集+bitset】
    目录题目大意解题思路code题目大意题目链接给出一张\(n\)个点\(m\)条边的连通无向图,边带边权\(w_i\)。有以下三种操作,共\(q\)次:\(\centerdot\)在点\(x,y\)之间加入一条边权为\(w_i\)的边,如果这是第\(i\)个此种操作,则记这条新边为第\(i\)条。\(\centerdot\)将第\(k......
  • 并查集优化 - 按大小合并时间复杂度证明
    并查集优化-按大小合并时间复杂度证明if(sz[b[x]].size()>sz[b[y]].size())swap(x,y);对于每个元素,当它当前所在的集合中,需要有其它大于该集合大小的集合,才会被遍历如果元素在一个大小\(1\)的集合中,会转移到大小\(2\)的集合中如果元素在一个大小\(2\)的集合中,会......
  • 并查集
    简述并查集其实是一个很有用的算法(至少我是这么认为的),很简单,代码也很好写,今天突然想写一下并查集。直接讲并查集不太好说,我们先看下面这一道题:洛谷P3367【模板】并查集【模板】并查集题目描述如题,现在有一个并查集,你需要完成合并和查询操作。输入格式第一行包含两个整数......
  • 超市-并查集应用
    【超市】【问题描述】超市里有N件商品,每个商品都有利润pi和过期时间di,每天只能卖一件商品,过期商品(即当天di<=0)不能再卖。求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。【输入格式】输入包含多组测试用例,测试用例最多30组。每组测试用例,以输入整数N开始,接下里输......
  • 并查集-讲课内容补全(未完
    施工中......先在这里给出我的并查集模板以下为比较常用的路径压缩intf[MAXN],n,m;voidclean(){for(inti=1;i<=n;i++)f[i]=i;}intfind(intx){if(x!=f[x])f[x]=find(f[x]);returnf[x];}voidadd(intx,inty){intfx=find(x),fy=find(y......
  • The Third Letter带权并查集
    Problem-1850H-Codeforces题意是给你a,b,c说明a在b后面c个单位(c<0就是在左边),每个位置只能有一个数,一共有n个位置,告诉你m个关系,问是否符合条件我们可以设置d[x]表示x到它的最早的父节点的距离,然后如果两个数父节点一样,那么c!=d[a]-d[b]时就说明不符合条件那么对于并查......
  • 算法刷题笔记--并查集的运用
    1、题目描述:一个城市中有两个犯罪团伙A和B,你需要帮助警察判断任意两起案件是否是同一个犯罪团伙所为,警察所获得的信息是有限的。假设现在有N起案件(N<=100000),编号为1到N,每起案件由团伙A或团伙B所为。你将按时间顺序获得M条信息(M<=100000),这些信息分为两类:D[a][b]其中[a]和[b]表示两......
  • 算法学习--并查集相关知识及例题
    一、并查集的定义二、基本操作1、初始化一开始,每个元素都是独立的集合#include<iostream>usingnamespacestd;constintmaxN=1000;intfather[maxN];intmain(){for(inti=1;i<=maxN;i++){father[i]=i;}return0;}2、查找递推版本://返......
  • 【学习笔记】并查集
    先来看百度百科上的定义:并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。并查集是一种树型的数据结构,用于处理一些不相交集合(disjointsets)的合......
  • 并查集
    在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内竞赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据......