#include<cstdio>usingnamespace std;int f[400010];intget(int x){if(f[x]== x)return x;return f[x]=get(f[x]);}intmain(){int n, m, q, i, x, y;scanf("%d%d%d",&n,&m,&q);for(i =1; i <= n + m; i++) f[i]= i;for(i =1; i <= q; i++){scanf("%d%d",&x,&y);
x =get(x), y =get(y + n);
f[x]= y;}int s =0;for(i =1; i <= n + m; i++)if(get(i)== i) s++;printf("%d", s -1);return0;}
eJOI2018 Problem D Chemical table题目大意n∗mn*mn∗m矩阵中已有若干点,只要有构成矩形(平行于坐标轴)的四个点中三个,就可以补充剩下一个,求把矩阵填满最少需要添加多少点。n,m≤2∗105n,m\le2*10^5n,m≤2∗105题解把行和列拆开看成二分图,发现每次添加点的操作,是在已经连通的三个点中把没连的边给连上,连通块的数量没有改变。同时,不难发现任何一个连通块中剩下的边都是可以直接加上的。现在需要把矩阵中所有点都填满,相当于所有的边都要连上,