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.
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.
* 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).
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.