二分图

二分图

什么是二分图

如果一个图中的点可以被分成两个部分,且每一个部分之间没有点相连,那么这就是一个二分图,如下:

erfentu1

可以发现,如果图中有长度为奇数的环(奇环),那么这一定不是一个二分图,如下:

关于二分图的一些基本概念

二分图的辨别及建图

由定义可知:二分图中直接相连的点被分在两边。所以可以对其进行染色

int color[maxn + 5];
bool paint(int u,int col) { // bool: false->不是二分图
  if (col[u] != 0) return col[u] == col; // 同一个点被染成不同的颜色->非二分图
  col[u] = col;
  bool flag = true;
  for (auto v : G0[u]) flag &= paint(v,3 - col); // 1/2染色
  return flag;
}

染色后从颜色 \(1\) 连向 \(2\)

int cnt1 = 0,cnt2 = 0; // 颜色1/2的数量
for (int u = 1;u <= n;u ++) {
  if (color[u] == 1) cnt1 ++;
  else cnt2 ++;
}
int num = (cnt1 <= cnt2 ? 1 : 2); // (细节)从少数点连向多数点
for (int u = 1;u <= n;u ++) {
  if (coler[u] == num) {
    
  }
}
细节
  1. 使左侧点小于右侧点:在匈牙利算法中,左侧 \(n\) 个点会枚举完,但右侧 \(m\) 个点不会,所以实际时间复杂度为 \(O(nm')\)\((m'\le m)\)

最大匹配数

选取最多的边,使得每个点只被选到不超过 \(1\) 次,则称选边数为最大匹配数

匈牙利算法

假设从左向右匹配:对于左侧的一个点 \(u_1\) ,向右侧与它相连的每一个点进行尝试匹配(假设当前尝试点为 \(v\))。

  • 如果 \(v\) 也没有被匹配,那就直接标记,答案增加。

    二分图3

    \(1\) 直接找到 \(2\) 匹配,\(2\) 直接找到 \(4\) 匹配)

  • 如果 \(v\) 被匹配了,且匹配 \(v\) 的点是 \(u_2\) ,那就考虑让 \(u_2\) 换一个点,给 \(u_1\) 空出位置 。

    二分图4

    \(2\) 想找 \(3\) 匹配,但是 \(3\) 已经被匹配了,所以 \(1\) 改为匹配 \(4\) ,给 \(2\) 让出位置)

时间复杂度分析:

假设左侧 \(n\) 个点,右侧 \(m\) 个点:

对于 \(n\) 个点中的每一个点都会尝试最多 \(m\) 次,所以理论时间复杂度\(O(nm)\)

实际上,在绝大多数情况下,这 \(m\) 个点不会全部都被搜索

代码及实现细节

int vis[maxn + 5];
int p[maxn + 5]; // 右侧点 v 被左侧点 p[v] 匹配
bool dfs(int u,int tar) { // 左侧点 u 点能否匹配到右侧的某一个点
  for (auto v : G[u]) {
    if (vis[v] == tar) continue; // 标记叠加(细节1)
    vis[v] = tar;
    if (p[v] == 0 || dfs(p[v],tar)) { // 对方没有被匹配/对方的匹配对象可以切换到其它的点
      p[v] = u;
      return true; // 匹配成功
    }
  }
  return false;
}
int main() {
  ...
  int ans = 0;
  for (int i = 1;i <= n;i ++) {     ans += dfs(i,i); // 能匹配到就增加答案
  }
  return 0;
}
细节
  1. 采用标记叠加:如果每一次都清空标记数组,那么时间复杂度会是标准的 \(O(nm)\)
  2. 建图可以建单向边(前提是这个图确定是二分图且明确左右侧各点):可以发现,dfs只枚举了从左向右的边

最小点覆盖

选取最少的点,使得每一条边的两个端点至少有 \(1\) 个点被选取

显然,最小点覆盖 \(=\) 最大匹配数

最大独立集

选取最多的点,使得每一个点都互不直接连接,则称这样的点集为最大独立集

可以发现,每一个匹配所对应的两个点只能选取一个,所以答案为:总点数 \(-\) 最大匹配数

二分图中的最大团

最大团:一个点集,使得由该点集诱导的图为完全图。

由定义知:每一个点都相连。

反过来就是每一个点都不相连,即最大独立集。

所以:最大团 \(=\) 补图的最大独立集

例题

二分图理论很简单,重点在于如何将问题转化为二分图问题。

【HEOI2012】朋友圈

传送门o( ̄▽ ̄)ブ

题目描述

在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.

一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目.两个国家看成是 AB 两国,现在是两个国家的描述:

  • A 国:每个人都有一个友善值,当两个 A 国人的友善值 \(a,b\),如果 \((a\mathbin{\mathrm{xor}} b) \bmod 2=1\),那么这两个人都是朋友,否则不是;
  • B 国:每个人都有一个友善值,当两个 B 国人的友善值 \(a,b\),如果 \((a\mathbin{\mathrm{xor}} b) \bmod 2=0\) 或者 \((a\mathbin{\mathrm{or}} b)\) 化成二进制有奇数个 \(1\),那么两个人是朋友,否则不是朋友.

A、B 两国之间的人也有可能是朋友,数据中将会给出 A、B 之间「朋友」的情况.

对于朋友的定义,关系是是双向的.

在 AB 两国,朋友圈的定义:一个朋友圈集合 \(S\),满足 \(S \subset A \cup B\),对于所有的 \(i,j \in S\)\(i\)\(j\) 是朋友.

观察两国的人分别如何才能成为朋友:

  • A国:只观察二进制末位,可以发现如果两人要成为朋友,那么需要一奇一偶,从而推出A国只能选 \(0\),\(1\),\(2\) 个数。
  • B国:稍微复杂,但可以发现,B国构成的补图是二分图

所以解法是:枚举 A国 的朋友,在 B国补图 中对与 A国相连的点最大独立集

posted @ 2026-08-26 01:06  Denia-kawaii  阅读(5)  评论(0)    收藏  举报