CodeForces - 1013D - Chemical table(并查集+二分图+思维)

9 篇文章 0 订阅
4 篇文章 0 订阅

CodeForces - 1013D - Chemical table(并查集+二分图+思维)

Innopolis University scientists continue to investigate the periodic table. There are n·m known elements and they form a periodic table: a rectangle with n rows and m columns. Each element can be described by its coordinates (r, c) (1 ≤ r ≤ n, 1 ≤ c ≤ m) in the table.

Recently scientists discovered that for every four different elements in this table that form a rectangle with sides parallel to the sides of the table, if they have samples of three of the four elements, they can produce a sample of the fourth element using nuclear fusion. So if we have elements in positions (r1, c1), (r1, c2), (r2, c1), where r1 ≠ r2 and c1 ≠ c2, then we can produce element (r2, c2).

Samples used in fusion are not wasted and can be used again in future fusions. Newly crafted elements also can be used in future fusions.

Innopolis University scientists already have samples of q elements. They want to obtain samples of all n·m elements. To achieve that, they will purchase some samples from other laboratories and then produce all remaining elements using an arbitrary number of nuclear fusions in some order. Help them to find the minimal number of elements they need to purchase.

Input
The first line contains three integers n, m, q (1 ≤ n, m ≤ 200 000; 0 ≤ q ≤ min(n·m, 200 000)), the chemical table dimensions and the number of elements scientists already have.

The following q lines contain two integers ri, ci (1 ≤ ri ≤ n, 1 ≤ ci ≤ m), each describes an element that scientists already have. All elements in the input are different.

Output
Print the minimal number of elements to be purchased.

Examples
Input
2 2 3
1 2
2 2
2 1
Output
0
Input
1 5 3
1 3
1 1
1 5
Output
2
Input
4 3 6
1 2
1 3
2 2
2 3
3 1
3 3
Output
1
Note
For each example you have a picture which illustrates it.

The first picture for each example describes the initial set of element samples available. Black crosses represent elements available in the lab initially.

The second picture describes how remaining samples can be obtained. Red dashed circles denote elements that should be purchased from other labs (the optimal solution should minimize the number of red circles). Blue dashed circles are elements that can be produced with nuclear fusion. They are numbered in order in which they can be produced.

Test 1

We can use nuclear fusion and get the element from three other samples, so we don’t need to purchase anything.

Test 2

We cannot use any nuclear fusion at all as there is only one row, so we have to purchase all missing elements.

Test 3

There are several possible solutions. One of them is illustrated below.

Note that after purchasing one element marked as red it’s still not possible to immidiately produce the middle element in the bottom row (marked as 4). So we produce the element in the left-top corner first (marked as 1), and then use it in future fusions.

因为图没有复制上读起来可能费劲,这是题目链接

题目大意:

给你一个nm的网格矩阵,然后给你一些点,如果出现这种情况在这里插入图片描述
那就自动补全矩形的四个角剩下的那个角。问,最少再加多少个点,能把这n
m的网格矩阵全部覆盖了

解题思路:

我们首先考虑一个问题:如果是一个空的n*m矩阵网格,最少需要多少个点才能把整个网格覆盖呢?
答案是 n+m-1 为什么呢?
在这里插入图片描述

看这个图,这是n+m-1个点 ,左上左下右下有了 那么右上自动就补上了
在这里插入图片描述
然后又可以补
在这里插入图片描述
然后可以继续补
在这里插入图片描述
就这么一直补,能把整个图都补满。

我们定义一个有效点的定义,就是那个点可以在 n+m-1中就定义为有效点,这样我们只要判断给出的q个点中,有多少个有效点,那我们用n+m-1减去已经存在的有效点就是最少需要继续填充的点。

那么问题又来了,如何判断他是个有效点呢??
这时候我们可以把矩阵转换成二部图处理,把矩阵的行看作x,矩阵的列看作y,如果 矩阵 (xi,yj)上有点,我们就把xi 和 yj连边。(这是一种处理矩阵常规操作)
在这里插入图片描述
这样就代表 有(x1,y1) (x1,y2) (x2,y1) 这样三个点。那么 这时候 (x2,y2)就是无效点。为什么呢?因为有这三个点后(x2,y2)就可以自动补上了
在这里插入图片描述
所以我们只要判断两个点是否连通,就可以判断这个点是不是有效点了,连通就是无效点,不连通,就是有效点,然后把这两个点merge()
判断连通与否最简单的方式就是并查集了

小结:

这个题虽然代码很短,但是思想确实很丰富的。
同时告诉了我们一种解决矩阵问题的方法——二部图

AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=2e5+10;
int f[maxn*2];
int n,m,q;
int find(int x)
{
	if(x==f[x])
		return f[x];
	else
		return f[x]=find(f[x]);
}
void merge(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	{
		f[fy]=fx;
	}
	return ;
}
void init()
{
	for(int i=1;i<=n+m;i++)
		f[i]=i;
	return ;
}
int main()
{	
	cin>>n>>m>>q;
	init();
	int cnt=q;
	int flag=0;
	int ans=0;
	for(int i=0;i<q;i++)
	{
		int a,b;
	//	cin>>a>>b;
		scanf("%d%d",&a,&b);
		if(find(a)==find(b+n))
		{
			cnt--;
			continue;
		}
		merge(a,b+n);
	}
	ans=n+m-1-cnt;

	cout<<ans<<endl;
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值