poj3041 Asteroids(二分图最小顶点覆盖、二分图匹配)

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

分别以n个行和n个列为结点,建立二分图,每一个星球对应一个连接其所在行和列的边,问题转化为求这个二分图的最小顶点覆盖。

在二分图中,有结论:最小顶点覆盖数=最大匹配数

自己yy了一个证明:

首先,我们证明不存在小于最大匹配数的最小顶点覆盖数。

这是显然的,因为这些顶点根本无法覆盖所有的匹配边。

接下来证明存在等于最大匹配数的最小顶点覆盖数。

首先证明,在最大匹配中,每条匹配边连接的两个顶点a,b最多只有一个与非匹配点有连边。

用反证法:假设a与c,b与d这件都有边,且c,d都不是匹配点,则可以去掉连接a,b的匹配边,加上连接a,c和连接b,d的匹配边,是匹配数+1,这与最大匹配矛盾。

这样,我们构造这样一个顶点集合:对于每条匹配边,选择其连接的两个点中的一个(如果两个点有与非匹配点有连边的点,则选那个点;否则随便选一个)。

这个集合中有最大匹配数个点。

我们证明:这个点集能覆盖所有的边。

若一条边是匹配边,则其显然被覆盖。

若一条边不是匹配边:

1)若其与某匹配顶点有连边,则该匹配顶点必在我们构造的点集中,所以该边被覆盖

2)若其连接着两个非匹配点,则可以增加这条边为匹配边,是匹配数+1,这与最大匹配矛盾,故此情况不成立

所以,这个点集能覆盖所有的边。

综上所述,在二分图中,最小顶点覆盖数=最大匹配数已得到证明。

 1 program rrr(input,output);
 2 const
 3   inf=123456789;
 4 type
 5   etype=record
 6      t,c,rev,next:longint;
 7   end;
 8 var
 9   e:array[0..20020]of etype;
10   a,cur,d:array[-505..505]of longint;
11   q:array[0..1010]of longint;
12   n,m,i,x,y,h,t,cnt,ans:longint;
13 procedure ins(x,y,c:longint);
14 begin
15    inc(cnt);e[cnt].t:=y;e[cnt].c:=c;e[cnt].next:=a[x];a[x]:=cnt;
16 end;
17 procedure add(x,y:longint);
18 begin
19    ins(x,y,1);ins(y,x,0);
20    e[cnt].rev:=cnt-1;e[cnt-1].rev:=cnt;
21 end;
22 function min(a,b:longint):longint;
23 begin
24    if a<b then exit(a) else exit(b);
25 end;
26 procedure bfs;
27 begin
28    for i:=-n to n+1 do d[i]:=-1;
29    h:=0;t:=1;q[1]:=0;d[0]:=0;
30    while h<t do
31       begin
32          inc(h);
33          i:=a[q[h]];
34          while i<>inf do
35             begin
36                if (d[e[i].t]=-1) and (e[i].c>0) then
37                   begin
38                      d[e[i].t]:=d[q[h]]+1;
39                      inc(t);q[t]:=e[i].t;
40                   end;
41                i:=e[i].next;
42             end;
43       end;
44 end;
45 function dfs(k,f:longint):longint;
46 var
47   ans,r,i:longint;
48 begin
49    if (k=n+1) or (f=0) then exit(f);
50    ans:=0;i:=cur[k];
51    while i<>inf do
52       begin
53          if (e[i].c>0) and (d[e[i].t]=d[k]+1) then
54             begin
55                r:=dfs(e[i].t,min(f,e[i].c));
56                dec(e[i].c,r);inc(e[e[i].rev].c,r);
57                ans:=ans+r;f:=f-r;
58                if f=0 then break;
59             end;
60          i:=e[i].next;
61          cur[k]:=i;
62       end;
63    if f>0 then d[k]:=-1;
64    exit(ans);
65 end;
66 begin
67    assign(input,‘r.in‘);assign(output,‘r.out‘);reset(input);rewrite(output);
68    readln(n,m);
69    cnt:=0;for i:=-n to n+1 do a[i]:=inf;
70    for i:=1 to n do begin add(0,-i);add(i,n+1); end;
71    for i:=1 to m do begin readln(x,y);add(-x,y); end;
72    ans:=0;
73    while true do
74       begin
75          bfs;
76          if d[n+1]=-1 then break;
77          for i:=-n to n+1 do cur[i]:=a[i];
78          ans:=ans+dfs(0,inf);
79       end;
80    write(ans);
81    close(input);close(output);
82 end.
时间: 2024-10-25 05:39:35

poj3041 Asteroids(二分图最小顶点覆盖、二分图匹配)的相关文章

UVa 2038 - Strategic game(二分图最小顶点覆盖 or 树形DP)

Strategic game Description Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of wh

hdu 1150 Machine Schedule(二分图-最小顶点覆盖)

Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5424    Accepted Submission(s): 2691 Problem Description As we all know, machine scheduling is a very classical problem in compu

UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi 和 Yi ,然后求二分图最小权完美匹配(流量为n也就是满载时,就是完美匹配). 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 200 + 10; 6 const int INF = 10000000

HDU ACM 1054 Strategic Game 二分图最小顶点覆盖?树形DP

分析:这里使用树形DP做. 1.最小顶点覆盖做法:最小顶点覆盖 == 最大匹配(双向图)/2. 2.树形DP: dp[i][0]表示i为根节点,并且该节点不放,所需的最少的点数. dp[i][1]表示i为根节点,并且该节点放,所需要的最少的点数. dp[i][0]=sum(dp[son[i][j]][1]) 该点不放,则它的儿子节点必须都放,只有这样之间的边才可以被覆盖. dp[i][1]=sum(min(dp[son[i][j]][0],dp[son[i][j]][1])) 该点放的话,则它的

POJ1325 Machine Schedule 【二分图最小顶点覆盖】

Machine Schedule Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11958   Accepted: 5094 Description As we all know, machine scheduling is a very classical problem in computer science and has been studied for a very long history. Scheduli

POJ 2195 Going Home 【二分图最小权值匹配】

传送门:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26151   Accepted: 13117 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit st

[POJ3041] Asteroids(最小点覆盖-匈牙利算法)

传送门 题意: 给一个N*N的矩阵,有些格子有障碍,要求我们消除这些障碍,问每次消除一行或一列的障碍,最少要几次. 解析: 把每一行与每一列当做二分图两边的点. 某格子有障碍,则对应行与列连边. 选出最少的点,使得所有边被覆盖. 最小点覆盖. ——代码 1 #include <cstdio> 2 #include <cstring> 3 #define M(x, a) memset(a, x, sizeof(a)) 4 5 using namespace std; 6 7 cons

poj3041 建图+最小顶点覆盖(最大匹配数)

这个题的意思是给你一个N*N的矩阵, 里面有K个星球, 我们可以让武器攻击矩阵的一行或者一列来使得这个星球被击碎, 现在问你最少需要几个这种武器才能把所有的星球击碎, 首先我们可以知道每个武器最多攻击一行一次, 因此最多有2*N个武器, 另外我们可以将武器看成顶点, 星球看成边,连接一副图,求出这个图的最小顶点覆盖数也就是最大匹配数即可, 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #i

POJ 3041.Asteroids 最小顶点覆盖

Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22905   Accepted: 12421 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 a