您的位置:首页 > 其它

HDU 4619 Warm up 2(贪心、并查集 | 二分图最大独立集)

2016-03-01 02:44 477 查看
题意:

1∗2的多米诺骨牌,n≤1000个横向的,m≤1000个纵向的

横向的之间互相没有交点,纵向也是

现要删掉几个,求剩下的最都没有交点的个数

分析:

一开始想只删纵的或者横的,然后反例就是这种图形



显然答案是4,删掉一横一纵

然后新的贪心姿势就来了,还是由于题目那个已知

应该是每个连通块,只留下横的或者竖的,留下多的那个

然后就能搞了,时间复杂度是O(n+m)

其实这是一个二分图,然后没交点就是二分图最大独立集。。。

时间复杂度是O(n2),边数最多是2n

贪心代码:

//
//  Created by TaoSama on 2016-02-28
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, m;

struct DSU {
int n, m;
int r
, p
;
int row
, col
;
void init(int _n, int _m) {
n = _n; m = _m;
for(int i = 1; i <= n + m; ++i) {
p[i] = i;
r[i] = 0;
if(i <= n) row[i] = 1, col[i] = 0;
else row[i] = 0, col[i] = 1;
}
}
int find(int x) {
return p[x] = p[x] == x ? x : find(p[x]);
}
void unite(int x, int y) {
x = find(x), y = find(y);
if(x == y) return;
if(r[x] > r[y]) swap(x, y);
p[x] = y;
if(r[x] == r[y]) ++ r[y];
row[y] += row[x]; row[x] = 0;
col[y] += col[x]; col[x] = 0;
}
int get() {
int ret = 0;
for(int i = 1; i <= n + m; ++i) {
//          printf("%d: %d %d\n", i, row[i], col[i]);
ret += max(row[i], col[i]);
}
return ret;
}
} dsu;

int row[105][105];

int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

while(scanf("%d%d", &n, &m) == 2 && (n || m)) {
dsu.init(n, m);
memset(row, 0, sizeof row);
for(int i = 1; i <= n; ++i) {
int x, y; scanf("%d%d", &x, &y);
row[x][y] = i, row[x + 1][y] = i;
}

for(int i = 1; i <= m; ++i) {
int x, y; scanf("%d%d", &x, &y);
if(row[x][y + 1]) dsu.unite(n + i, row[x][y + 1]);
if(row[x][y]) dsu.unite(n + i, row[x][y]);
}

int ans = dsu.get();
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息