二分图

二分图

二分图:若能将无向图G=(V,E)的顶点V划分为两个交集为空的顶点集,并且任意边的两个端点都分属于两个集合,则称图G为一个为二分图。

完全二分图

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边...形成的路径叫交替路。

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路

二分图判定

c[i]代表每个点涂的颜色,涂色为1或2,通过判断颜色是否冲突来判断二分图

vector<int> edge[N + 1];
int n, m, c[N + 1];
bool dfs(int x) {//染色
    for (auto y : edge[x]) {
        if (!c[y]) {
            c[y] = 3 - c[x];
            if (!dfs(y)) return false;
        }
        else if (c[x] == c[y]) return false;
    }
    return true;
}

bool check() {
    memset(c, 0, sizeof(c));
    for (int i = 1; i <= n; i++) {
        if (!c[i]) {
            c[i] = 1;
            if (!dfs(i)) return false;
        }
    }
    return true;
}

void solve() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    if (check()) printf("Yes\n");
    else printf("No\n");
}

二分图匹配

概念

由增广路的性质,增广路中的匹配边总是比未匹配边多一条,所以如果我们放弃一条增广路中的匹配边,选取未匹配边作为匹配边,则匹配的数量就会增加。匈牙利算法就是在不断寻找增广路,如果找不到增广路,就说明达到了最大匹配。匈牙利算法(二分图)博客园

vector<int>edge[N + 1];
int n, m, n1, n2, v[N + 1];//v[i]记录匹配情况
bool b[N + 1];
bool find(int x) {
    b[x] = true;
    for (auto y : edge[x]) {
        if (!v[y] || (!b[v[y]] && find(v[y]))) {
            v[y] = x;
            return true;
        }
    }
    return false;
}
int match() {
    int ans = 0;
    for (int i = 1; i <= n1; i++) {
        memset(b, false, sizeof(b));
        if (find(i)) ans++;
    }
    return ans;
}

棋盘覆盖问题:

将棋盘涂成黑白交错的颜色,进行二分图匹配,黑向白连边

最大独立集

最大独立集是指:在图中选出最多的点,满足他们两两之间没有边相连

最大独立集等于总点数-最大匹配数

注意如何建立二分图

二分图最小点覆盖:选择最少的路径,使得每条边至少有一个点被选中;

最小点覆盖等于等于总点数-边的最大匹配数

注意二分图的拆分方式

Last updated