学习Hall’s Marriage Theorem

Posted cly-none

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习Hall’s Marriage Theorem相关的知识,希望对你有一定的参考价值。

其实是在做题时遇到这个定理的。
这个定理的图论意义是:

对于一个二分图(G={X+Y,E}),它满足:
(forall W subseteq X, , |W| leq |N_G(W)|) (iff)(X)中的每个结点都有匹配.
其中(N_G(W))为图(G)中所有与(W)相连的结点的集合。

必要性显然。
对于充分性,不会……以后再补充。

由这个定理,我们能得到一个推论:

二分图(G)的最大匹配(M)等于(|X| - max (|W| - |N_G(W)|)).

顺便一提,我们允许(W = emptyset),故(max (|W| - |N_G(W)|) geq 0)
我们分两步来证明这个推论。在此,我们假设(W_0 subseteq X)满足(|W_0| - |N_G(W_0)| = max (|W| - |N_G(W)|))

  • 证明:(M leq |X| - max (|W| - |N_G(W)|)).
    考虑(W_0),即使(N_G(W_0))中的每个结点都与(W_0)中的结点匹配,也会有(|W_0| - |N_G(W_0)|)个结点得不到匹配。故(X)中至少有(|W_0| - |N_G(W_0)|)个结点得不到匹配。因此,(M leq |X| - max (|W|))
  • 证明:(M geq |X| - max (|W| - |N_G(W)|)).
    我们在(Y)中添加(max (|W| - |N_G(W)|)个结点与(X)中所有结点相连得到新图(G`),那么,(|W_0| - |N_{G`}(W_0)| = 0)。由Hall‘s Marriage Theorem可知,图(G`)(X)的每个元素都有匹配。而对于(W_0),因为(|W_0| = |N_{G`}(W_0)|),所以(N_{G`}(W_0))中的每个元素都与(W_0)中的元素匹配,可得我们新加入的结点都有匹配。因此,除(W_0)中有(|W_0|-|N_G(W_0)|)个结点与新加入的结点匹配之外,(X)中其余结点都与原来(Y)中的结点匹配。故在删去新加的结点后,(X)中至多有(|W_0| - |N_G(W_0)|)个结点没有匹配。则(M geq |X| - max (|W| - |N_G(W)|))

那么,这个定理及其推论有什么用呢?因为要枚举(X)的所有子集,所以一般是没什么用的。然而,某些有特殊性质的二分图的最大匹配问题,会使用这个定理及其推论来转化问题。

例题

arc076F Exhausted?

题意:给出二分图(G={X+Y,E})(X)中的所有结点满足:若其编号为(i),则只与(Y)中编号小于等于(L_i)或编号大于等于(R_i)的结点连边。给出(|X|,|Y|)和所有的(L_i,R_i),求(G)的最大匹配(M)。(输出(|X|-M))
(|X|,|Y| leq 2 imes 10^5).

有了这个定理,问题就简单了。我们只要求(max (|W| - |N_G(W)|))。对于(W subseteq X)(N_G(W))就是形如(Y - [l,r])的形式,其中([l,r])(Y)中一个编号的区间。我们枚举(r),用线段树实现区间加和区间查最大值即可。具体做法不再阐述。
时间复杂度(O(n log n))

#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int n,m,ans,cnt;
struct data {
  int l,r;
} ordl[N],ordr[N];
bool cmpl(data a,data b) {
  return a.l < b.l;
}
bool cmpr(data a,data b) {
  return  a.r < b.r;
}
struct node {
  int mx,tag;
} t[N << 2];
void puttag(int x,int val) {
  t[x].mx += val;
  t[x].tag += val;
}
void push_down(int x) {
  puttag(x<<1,t[x].tag);
  puttag(x<<1|1,t[x].tag);
  t[x].tag = 0;
}
void push_up(int x) {
  t[x].mx = max(t[x<<1].mx,t[x<<1|1].mx);
}
void modify(int l,int r,int val,int x=1,int lp=1,int rp=m) {
  if (l > rp || r < lp) return;
  if (lp >= l && rp <= r) {
    puttag(x,val);
    return;
  }
  if (t[x].tag) push_down(x);
  int mid = (lp + rp) >> 1;
  modify(l,r,val,x<<1,lp,mid);
  modify(l,r,val,x<<1|1,mid+1,rp);
  push_up(x);
}
int query(int l,int r,int x=1,int lp=1,int rp=m) {
  if (l > rp || r < lp) return 0;
  if (lp >= l && rp <= r) return t[x].mx;
  if (t[x].tag) push_down(x);
  int mid = (lp + rp) >> 1;
  return max(query(l,r,x<<1,lp,mid),query(l,r,x<<1|1,mid+1,rp));
}
int main() {
  int a,b;
  scanf("%d%d",&n,&m);
  ans = max(0,n - m);
  cnt = n;
  for (int i = 1 ; i <= cnt ; ++ i) {
    scanf("%d%d",&a,&b);
    a ++;
    b --;
    if (a > b) {
      i --, cnt --;
      continue;
    }
    ordl[i] = (data) {a,b};
    ordr[i] = (data) {a,b};
  }
  sort(ordl+1,ordl+cnt+1,cmpl);
  sort(ordr+1,ordr+cnt+1,cmpr);
  int pl = 1, pr = 1;
  for (int i = 1 ; i <= m ; ++ i) {
    modify(1,i,1);
    for (; ordl[pl].l <= i && pl <= cnt ; ++ pl)
      modify(ordl[pl].l,m,1);
    ans = max(ans,query(1,i) - m);
    for (; ordr[pr].r <= i && pr <= cnt ; ++ pr)
      modify(ordr[pr].l,m,-1);
  }
  printf("%d
",ans);
  return 0;
}



小结:学了一个没卵用的定理。也挺好奇还有哪些二分图能用到这个定理。


以上是关于学习Hall’s Marriage Theorem的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 981F. Round Marriage

Marriage Ceremonies LightOJ - 1011

Marriage is Stable

狄尔沃斯定理(Dilworth's theorem)

Wilson's Theorem

HDU3605:Marriage Match IV