题目链接
给一个
nXm,n≤2e5,m≤2e5
n
X
m
,
n
≤
2
e
5
,
m
≤
2
e
5
的格子,其中有
q
q
个点 , 有一种操作,存在这样的三个点 :
(r1,c1),(r2,c1),(r1,c2)
(
r
1
,
c
1
)
,
(
r
2
,
c
1
)
,
(
r
1
,
c
2
)
就能构造出 另外一个点
(r2,c2)
(
r
2
,
c
2
)
, 问至少要添加多少个点才能将这个地图填满。
分析
- 用图论的建模,将点 (r,c) ( r , c ) 映射为一个二分图,左边是 r r , 右边是 所构成的边。
- 证明任意一条边 (x,y) ( x , y ) 可以通过其连通分量用题意中的公式产生
- 答案就是连通分量数减掉1
证明参见 http://codeforces.com/blog/entry/60920
AC code
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
/**
* @author zouzhitao
*
*/
public class Main {
public static Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in),65536));
public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public final static int MAX_ARRAY_SIZE = 200000+10;
public static List<Integer>[] G = new List[MAX_ARRAY_SIZE*2];
public static int n,m,q;
public static boolean[] vis = new boolean[MAX_ARRAY_SIZE*2];
public static int component() {
Arrays.fill(vis, 1,n+m+1,false);
int ret =0;
for(int i=1 ; i <=n+m ; ++i)
if(!vis[i]){
ret++;
dfs(i);
}
return ret;
}
private static void dfs(int u) {
vis[u] = true;
for(int v : G[u]){
if(!vis[v])dfs(v);
}
}
public static String[] tokenPoll;
public static void main(String[] args) {
n = Integer.parseInt(in.next());
m = Integer.parseInt(in.next());
q = Integer.parseInt(in.next());
for(int i=1 ; i<=n+m ; ++i)G[i] = new ArrayList<>();
while (q-->0) {
int x= Integer.parseInt(in.next());
int y = Integer.parseInt(in.next());
y+=n;
G[x].add(y);
G[y].add(x);
}
out.println(component()-1);
out.flush();
}
}