zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    公用导航栏的根据url控制选中导航js
    页面切换出动晃动解决
    redis五大数据类型
    redis简介
    Linux安装redis
    各种锁的理解
    原子引用
    理解CAS
    彻底玩转单例模式
    Volatile
  • 原文地址:https://www.cnblogs.com/Currier/p/6535734.html
Copyright © 2011-2022 走看看