HNU 2014 Warm Up 15 E Easy Delete 最小点覆盖=最大匹配数

题目链接:点击打开链接

Easy Delete
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB
Total submit users: 8, Accepted users: 4
Problem 13103 : No special judgement
Problem description

huicpc0215 has downloaded a lots of files in his desktop. Since there are too many files in the desktop, he wants to delete some files in the desktop. But some files can’t be deleted.

Each time he can choose one row or column to delete. But attention he can’t choose one row or column that has a file which can’t be deleted. Given the position of all files, please get the minimum steps for huicpc0215 to delete all files that he wants to delete.

Input

There are multiple test cases. Each test case containing:

The first line contains one integer: N (1 <= N <= 1000) , N lines follows. Each line contains three integers: F (0 <= F <= 1), X (-1e9 <= V <= 1e9), Y (-1e9 <= V <= 1e9). F=0 means this file can’t be delete. F=1 means this file must be deleted. And X and Y
are the position of the file in the desktop.

Output

If huicpc0215 can achieve his goal, print minimum steps to achieve his goal, otherwise print “Sorry” in one line.

Sample Input
2
0 1 1
1 1 2
3
0 1 1
0 2 2
1 1 2
3
1 1 1
1 2 2
1 1 2
Sample Output
1
Sorry
2

题意:

给定n个二维坐标上的点

下面n行:

Fi, xi, yi

若Fi=0表示这个点不能删除

若Fi=1表示这个点必须删除

每次操作可以选任意一行或一列(注意这行(列)里不能有不可删除的点),把这行上的所有可删除点删除

问:最小操作次数。

思路:

若都是必须删除的点,那么就是经典的最小点覆盖

这题中:可删除点有3种

1、x y坐标都存在不能删除的点,这时候就输出 Sorry

2、x或y存在不能删除的点,那么我们强行选这个点的行(或列),并把该行所有点删掉。

3、经过上面2种操作就只有x y都不存在 不能删除点,这种点就是最小点覆盖。

补充最小点覆盖知识:

对于二部图,图中有一些边。

要选择最少的点使得所有边都被覆盖(当这条边的任意一个端点被选择或者两个端点同时被选择,则称这条边被覆盖了)

yy得证:

最小顶点覆盖数 = 最大匹配数

而那些没有被选择的点统称最大团

所以最大团 = X集点数+Y集点数 - 最小点覆盖数

即 :最大团 = X集点数+Y集点数 - 最大匹配数

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include<queue>
#include<algorithm>
#include<math.h>
using namespace std;
#define N 1005
int lef[N], pn;//lef[v]表示Y集的点v 当前连接的点 , pn为x点集的点数
bool T[N];     //T[u] 表示Y集 u 是否已连接X集
vector<int>G[N]; //匹配边  G[X集].push_back(Y集)  注意G 初始化

int sx[N], sy[N];
bool match(int x){ // x和Y集 匹配 返回x点是否匹配成功
	for(int i=0; i<G[x].size(); i++)
	{
		int v = G[x][i];
		if(!T[v])
		{
			T[v] = true;
			if(lef[v] == -1 || match( lef[v] ))   //match(lef[v]) : 原本连接v的X集点 lef[v] 能不能和别人连,如果能 则v这个点就空出来和x连
			{
				lef[v] = x;
				return true;
			}
		}
	}
	return false;
}

int solve(){
    memset(lef, -1, sizeof(lef));
    int ans = 0;
    for(int i = 1; i <= pn; i++)
    {
        memset(T, 0, sizeof T);
        if(match(i)){
       // 	printf("ok:%d\n", i);
			ans++;
		}
    }
    return ans;
}
vector<int>gx, gy;
int f[N], x[N], y[N], a[N], b[N];
int n, papa;
bool input(){
	gx.clear(); gy.clear();

	for(int i = 1; i <= n; i++)
	{
		scanf("%d %d %d", &f[i], &x[i], &y[i]);
		gx.push_back(x[i]);
		gy.push_back(y[i]);
	}
	sort(gx.begin(), gx.end());
	sort(gy.begin(), gy.end());
	gx.erase(unique(gx.begin(), gx.end()), gx.end());
	gy.erase(unique(gy.begin(), gy.end()), gy.end());
	memset(sx, 0, sizeof sx);
	memset(sy, 0, sizeof sy);
	memset(a, 0, sizeof a);
	memset(b, 0, sizeof b);
	for(int i = 1; i <= n; i++)
	{
		x[i] = lower_bound(gx.begin(), gx.end(), x[i]) - gx.begin()+1;
		y[i] = lower_bound(gy.begin(), gy.end(), y[i]) - gy.begin()+1;
		if(f[i] == 0)
		{
			sx[x[i]] = sy[y[i]] = 1;
		}
	}
	for(int i = 1; i <= (int)gx.size(); i++)G[i].clear();
	papa = 0;
	for(int i = 1; i <= n; i++)
	{
		if(f[i] == 0)continue;
		if(sx[x[i]] && sy[y[i]])
			return false;
		if(sx[x[i]])
		{
			if(b[y[i]])continue;
			b[y[i]] = 1; papa++;
		}
		else if(sy[y[i]])
		{
			if(a[x[i]])continue;
			a[x[i]] = 1; papa++;
		}
	}
	for(int i = 1; i <= n; i++)
	{
		if(f[i] == 0)continue;
		if(a[x[i]] || b[y[i]])continue;
		G[x[i]].push_back(y[i]);
	}
	return true;
}
int main() {
	while(~scanf("%d", &n)){
 	if(false == input())
		{
			puts("Sorry"); continue;
		}
		pn = (int)gx.size();
		int ans = solve();
//		printf("(匹配边数%d)\n", ans);
		ans = papa+ans;
	//	printf("pn:%d\nGX:", pn);		for(int i = 0; i < gx.size(); i++)printf("%d ", gx[i]);cout<<"\n"<<"GY:";		for(int i = 0; i < gy.size(); i++)printf("%d ", gy[i]);puts("");
			printf("%d\n", ans);
	}
	return 0;
}/*
4
1 1 1
1 2 2
1 1 2
0 2 1

6
1 1 1
1 2 2
1 1 2
0 2 1
0 2 3
0 1 0

3
1 1 2
1 1 3
1 1 4

5
1 0 0
1 1 0
0 2 0
1 1 1
0 2 1

25
0 1 1
0 1 2
0 1 3
0 2 1
0 2 2

0 2 3
0 3 1
0 3 2
0 3 3
1 0 0

1 1 0
1 2 0
1 3 0
1 4 0
1 0 2

1 4 2
1 0 1
1 4 1
1 0 3
1 4 3

1 0 4
1 4 4
1 1 4
1 2 4
1 3 4

25
1 1 1
1 1 2
1 1 3
1 2 1
0 2 2

1 2 3
1 3 1
1 3 2
1 3 3
1 0 0

1 1 0
1 2 0
1 3 0
1 4 0
1 0 2

1 4 2
1 0 1
1 4 1
1 0 3
1 4 3

1 0 4
1 4 4
1 1 4
1 2 4
1 3 4

3
1 1 1
1 1 1
1 1 2

*/
时间: 2024-08-06 11:36:55

HNU 2014 Warm Up 15 E Easy Delete 最小点覆盖=最大匹配数的相关文章

(Easy) Delete Node in a Linked List - LeetCode

Description: Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. Given linked list -- head = [4,5,1,9], which looks like following: Example 1: Input: head = [4,5,1,9], node = 5 Output: [4,1,9]

hunnu OJ 11564 Easy Delete(二维坐标的离散化处理+最大匹配)

题意:?给出两类点坐标 –一类可删除 –一类不可删除 ?选出最少的行或列,删除所有要删除的点. 思路: ?首先看到坐标范围很大,第一点要做的就是离散化. ?接着,将行看成二分图的X集合,将列看成二分图的Y集合,于是,我们要删除的点,就是X连接Y的一条边. ?最后,我们要求的就是最少的点覆盖所有的边.在二分图中,最大匹配==最小点覆盖. 需要注意的地方: ?判断每一个要删除的点,如果X方向和Y方向都有不能删除的点,就是Sorry. ? ?如果只有一个方向有,则必须使用另外一个方向删除该行/列的所有

泛函编程(15)-泛函状态-随意数产生器

对于OOP程序员来说,泛函状态变迁(functional state transition)是一个陌生的课题.泛函状态变迁是通过泛函状态数据类型(functional state)来实现的.State是一个出现在泛函编程里的类型(type).与其它数据类型一样,State同样需要自身的一套泛函操作函数和组合函数(combinators),我们将在以下章节中讨论有关State数据类型的设计方案. 在正式介绍State类型前,我们先从随意数产生器(RNG: Random Number Generat

hdu 1054 最小点覆盖

Sample Input 4 0:(1) 1 1:(2) 2 3 2:(0) 3:(0) 5 3:(3) 1 4 2 1:(1) 0 2:(0) 0:(0) 4:(0) Sample Output 1 2 最小点覆盖=最大匹配数 水题,懒的拍了 1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 #include<vector>

poj 2226 Muddy Fields(二分图最小点覆盖)

B - Muddy Fields Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2226 Description Rain has pummeled the cows' field, a rectangular grid of R rows and C columns (1 <= R <= 50, 1 <= C <

POJ 3041 Asteroids (二分图最小点覆盖)

题目链接:http://poj.org/problem?id=3041 在一个n*n的地图中,有m和障碍物,你每一次可以消除一行或者一列的障碍物,问你最少消除几次可以将障碍物全部清除. 用二分图将行(左边)和列(右边)用障碍物联系起来,比如(2,3)有个障碍物,那么左边的2和右边的3连边.边的个数就是障碍物的个数,点的个数就是次数,所以问题就变成了用少的点覆盖全部的边,也就是最小点覆盖问题.二分图中,最小点覆盖=最大匹配数. 1 //最小点覆盖 = 最大匹配 2 #include <iostre

[UVALive] 6492 Welcome Party(最小点覆盖)

6492 Welcome Party For many summers, the Agile Crystal Mining company ran an internship program for students. Theygreatly valued interns' ability to self-organize into teams. So as a get-to-know-you activity duringorientation, they asked the interns

图论之二分图匹配

一.二分图最大匹配 Edmonds于1965年提出了匈牙利算法,解决了求取二分图最大匹配的问题.其算法思想是将初始匹配通过迭代寻找增广路径得到最大匹配,每次迭代得到的匹配大小加1. 增广路径的表现形式是一条“交错路径”,第一条边是目前没有参与匹配的,第二条参与匹配,第四条边没有参与......最后一条边没有参与匹配,并且始点和终点还没有被选过.那么对于这样一条路径,我们可以将第一条边改为已匹配,第二条边改为未匹配...以此类推.也就是将所有的边进行"反色",容易发现这样修改以后,匹配仍

它处资料:二分图最大匹配的匈牙利算法

资料出处:点击打开链接 匈牙利算法 二分图最大匹配的匈牙利算法:  二分图是这样一个图,它的顶点能够分类两个集合X和Y,全部的边关联在两个顶点中.恰好一个属于集合X.还有一个属于集合Y. 最大匹配: 图中包括边数最多的匹配称为图的最大匹配. 完美匹配: 假设全部点都在匹配边上.称这个最大匹配是完美匹配. 最小覆盖: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和当中一个点关联.能够证明:最少的点(即覆盖数)=最大匹配数 最小路径覆盖: 用尽量少的不相交简单路径覆盖有向无环图G的全