HDU 4619 Warm up 2(贪心、并查集 | 二分图最大独立集)
2016-03-01 02:44
477 查看
题意:
1∗2的多米诺骨牌,n≤1000个横向的,m≤1000个纵向的
横向的之间互相没有交点,纵向也是
现要删掉几个,求剩下的最都没有交点的个数
分析:
一开始想只删纵的或者横的,然后反例就是这种图形
显然答案是4,删掉一横一纵
然后新的贪心姿势就来了,还是由于题目那个已知
应该是每个连通块,只留下横的或者竖的,留下多的那个
然后就能搞了,时间复杂度是O(n+m)
其实这是一个二分图,然后没交点就是二分图最大独立集。。。
时间复杂度是O(n2),边数最多是2n
贪心代码:
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; }
相关文章推荐
- 1.一些 贪心算法 的简单思维题:
- 贪心算法——字典序最小问题
- 贪心算法——区间调度问题
- 1611:The Suspects
- HDU-1213-How Many Tables
- Jump Game I,II 贪心
- Longest Consecutive Sequence,Distinct Subsequences,Interleaving String,Scramble String
- Wildcard Matching
- 贪心法实现无向图的划分 代码
- 贪心题目循环和控制台折行
- 并查集_POJ 1182_食物链
- SARS病毒传染 并查集
- HDU 1213
- HDOJ 1009
- CSU1307 并查集+SPFA
- 【解题报告】【USACO】酸奶工厂
- 【解题报告】【】交谊舞
- POJ 1328
- Best Cow Line
- HDU 1009 Fatmouse's Trade