版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/82467126
原题地址:http://codeforces.com/contest/1013/problem/D
题意:给你一个 的矩形,一开始有 个格子上被标记。对于任意两行两列,如果交汇的四个格子中有三个被标记,那么第4个会被自动标记。问你至少需要手动标记几个格子,使得整个矩形内的格子都被标记。
思路:这题一开始真的想不到可以用二分图建图然后求强连通分量来做.
具体解释可以看这里https://blog.csdn.net/qq_39984146/article/details/81321885
ac代码:
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 4e5 + 5;
const int mod = 1e9 + 7;
int n, m, q;
struct node {
int v, nxt;
} e[maxn << 1];
int tot, head[maxn];
void init_head() {
tot = 0;
CLR(head, -1);
}
void add_edge(int u, int v) {
e[tot].v = v;
e[tot].nxt = head[u];
head[u] = tot++;
}
int cnt;
int vis[maxn];
void dfs(int u) {
vis[u] = 1;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
if (vis[v]) continue;
dfs(v);
}
}
int main() {
cnt = 0;
CLR(vis, 0);
scanf("%d%d%d", &n, &m, &q);
init_head();
for (int i = 1; i <= q; i++) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, n + v);
add_edge(n + v, u);
}
for (int i = 1; i <= n + m; i++) {
if (vis[i] == 0) {
cnt++;
dfs(i);
}
}
printf("%d\n", cnt - 1);
return 0;
}