题目大意:
给定一个 n∗m n ∗ m 的矩阵(可以理解为元素周期表),当三个元素形成一个矩形的三个角的时候,另外一个角的元素便可以自动生成,现在有 q q <script type="math/tex" id="MathJax-Element-87">q</script>个元素并且已知他们的位置,求把这个矩阵都填满的情况下最小需要额外添加几种新的元素。
思路:
表示这个题目考试的时候好多人都A了但是我怎么想都想不出来,后来看了别人的代码我才知道怎么做。
来考虑在什么情况下元素才会连续生成,即在若干个方块可以形成一个带拐角的图形且拐角处无中断的时候,这些方块的所有的横坐标和所有的纵坐标两两组合形成的点都可以不耗费新的元素而直接生成。从横坐标和纵坐标的角度来考虑的话就是这些坐标通过原有的元素连接而形成了连通块。所以为了让所有的横坐标以及纵坐标在一个连通块里面的话就只要统计原有的连通块的个数然后耗费个数减一个新元素把他们连在一起就好了。
/*=========================
Author : ylsoi
Problem : CF1013D.cpp
Algorithm : bingchaji
Time : 2018.7.31
========================*/
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;
using namespace std;
void File(){
freopen("CF1013D.in","r",stdin);
freopen("CF1013D.out","w",stdout);
}
const int maxn=2e5+10;
int n,m,q,fa[maxn<<1],ans;
bool vis[maxn<<1];
int find(int x){return fa[x]==x ? x : fa[x]=find(fa[x]);}
int main(){
File();
scanf("%d%d%d",&n,&m,&q);
REP(i,1,n+m)fa[i]=i;
int x,y;
REP(i,1,q){
scanf("%d%d",&x,&y);
y+=n;
fa[find(x)]=find(y);
}
REP(i,1,n+m)if(!vis[find(i)]){
vis[find(i)]=1;
++ans;
}
printf("%d\n",ans-1);
return 0;
}