poj 3041 二分图最大匹配(最小点覆盖问题)

Asteroids
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 12937 Accepted: 7040

Description

Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the grid.

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.

Input

* Line 1: Two integers N and K, separated by a single space.
* Lines 2..K+1: Each line contains two space-separated integers R and C (1 <= R, C <= N) denoting the row and column coordinates of an asteroid, respectively.

Output

* Line 1: The integer representing the minimum number of times Bessie must shoot.

Sample Input

3 4
1 1
1 3
2 2
3 2

Sample Output

2

Hint

INPUT DETAILS:
The following diagram represents the data, where "X" is an asteroid and "." is empty space:
X.X
.X.
.X.


OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and (1,3), and then she may fire down column 2 to destroy the asteroids at (2,2) and (3,2).

Source

USACO 2005 November Gold

注意这道题是 不能用贪心算法求解的,因为有如下反例:
1100
1010
1001
0000
贪心求解的结果是4.而正确的结果是3.


重要定理: 二分图最小点覆盖数等于二分图的最大匹配数。
将横坐标视为n个独立的点,将纵坐标的值视为另外n个独立的点。
则每一个陨石可以视为一个匹配。
现在要求的就是 最小的点,可以将所有陨石都覆盖到。
用匈牙利算法求解如下:

提交记录:
1.样例未果。需要将横坐标处理为前n个点,纵坐标处理为n+纵坐标的值,也就是后n个点。同时, 需要修改模板中的0-V-1 为 0-V
2.Runtime Error。忘记修改MAXV的值了。。。网络流和 二分图算法尤其要注意最大的点个数。
3.Accepted!

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          #include 
         
           #include 
          
            #define oo 1000000 #define MAXV 510*2//乘以2! using namespace std; int V, m; vector 
           
             G[MAXV]; int match[MAXV]; bool used[MAXV]; void add_edge(int u, int v) { G[u].push_back(v); G[v].push_back(u); } bool dfs(int v) { used[v] = true; for (int i = 0; i < G[v].size(); i++) { int u = G[v][i], w = match[u]; if (w < 0 || !used[w] && dfs(w)) { match[v] = u; match[u] = v; return true; } } return false; } int bipartite_matching() { int res = 0; int v; for (v = 0; v <= V; v++) match[v] = -1;//这两句修改为0-V。因为模板多一个结点实际上是没关系的。如果这个结点没有边相连,那也不会处理它 for (v = 0; v <= V; v++) { if (match[v] < 0) { memset(used, 0, sizeof(used)); if (dfs(v)) res++; } } return res; } int main() { cin >> V >> m; int i; for (i = 1; i <= m; i++) { int a, b; cin >> a >> b; add_edge(a, V + b); //注意这里!虽然都是坐标,从1-V,但横坐标和纵坐标是不同的点。所以结点的编号是不一样的!!!一定要区分开来 } V *= 2;//总坐标乘以2 cout << bipartite_matching() << endl;//二分图的最大匹配数等于二分图的最大点集覆盖数 return 0; } 
            
           
          
        
       
       
      
      
     
     
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值