acwing算法提高之图论--二分图

目录

  • [1 介绍](#1 介绍)
  • [2 训练](#2 训练)
  • [3 参考](#3 参考)

1 介绍

本专题用来记录二分图的题目。

以下条件互相等价:

  1. 一个图是二分图。
  2. 染色法过程中不存在矛盾。
  3. 图中不存在奇数环。

二分图本质上是一个无向图的问题!

结论:

最大匹配数 = 最小点覆盖 = 总点数 - 最大独立集 = 总点数 - 最小路径覆盖

2 训练

题目1:257关押罪犯

C++代码如下,

cpp 复制代码
#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

typedef pair<int, int> PII;

const int N = 20010;
int n, m;
vector<vector<PII>> g(N);
int color[N];

bool dfs(int a, int c, int mid) {
    color[a] = c;
    
    //看结点a能走到哪儿
    for (auto [b, w] : g[a]) {
        if (w <= mid) continue; 
        if (!color[b] && !dfs(b, 3 - c, mid)) return false;
        if (color[b] && color[b] == c) return false;
    }
    return true;
}

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

int main() {
    cin >> n >> m;
    int a, b, w;
    while (m--) {
        cin >> a >> b >> w;
        g[a].emplace_back(b, w);
        g[b].emplace_back(a, w);
    }
    
    int l = 0, r = 1e9;
    int res = -1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            r = mid - 1;
            res = mid;
        } else {
            l = mid + 1;
        }
    }
    
    cout << res << endl;
    
    return 0;
}

题目2372棋盘覆盖

C++代码如下,

cpp 复制代码
#include <cstring>
#include <iostream>
#include <algorithm>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 110;

int n, m;
PII match[N][N];
bool g[N][N], st[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

bool find(int x, int y) {
    for (int i = 0; i < 4; ++i) {
        int a = x + dx[i], b = y + dy[i];
        if (a && a <= n && b && b <= n && !g[a][b] && !st[a][b]) {
            st[a][b] = true;
            PII t = match[a][b];
            if (t.x == -1 || find(t.x, t.y)) {
                match[a][b] = {x, y};
                return true;
            }
        }
    }
    return false;
}

int main() {
    cin >> n >> m;
    
    while (m--) {
        int x, y;
        cin >> x >> y;
        g[x][y] = true;
    }
    
    memset(match, -1, sizeof match);
    
    int res = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if ((i + j) % 2 && !g[i][j]) {
                memset(st, 0, sizeof st);
                if (find(i, j)) res++;
            }
        }
    }
    
    cout << res << endl;
    
    return 0;
}

题目3376机器任务

C++代码如下,

cpp 复制代码
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

int n, m, k;
int match[N];
bool g[N][N], st[N];

bool find(int x) {
    for (int i = 0; i < m; ++i) {
        if (!st[i] && g[x][i]) {
            st[i] = true;
            if (match[i] == -1 || find(match[i])) {
                match[i] = x;
                return true;
            }
        }
    }
    return false;
}

int main() {
    while (cin >> n, n) {
        cin >> m >> k;
        memset(g, 0, sizeof g);
        memset(match, -1, sizeof match);
        
        while (k--) {
            int t, a, b;
            cin >> t >> a >> b;
            if (!a || !b) continue;
            g[a][b] = true;
        }
        
        int res = 0;
        for (int i = 0; i < n; ++i) {
            memset(st, 0, sizeof st);
            if (find(i)) res++;
        }
        
        cout << res << endl;
    }
    
    return 0;
}

题目4378骑士放置

C++代码如下,

cpp 复制代码
#include <cstring>
#include <iostream>
#include <algorithm>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 110;

int n, m, k;
PII match[N][N];
bool g[N][N], st[N][N];

int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};

bool find(int x, int y) {
    for (int i = 0; i < 8; ++i) {
        int a = x + dx[i], b = y + dy[i];
        if (a < 1 || a > n || b < 1 || b > m) continue;
        if (g[a][b]) continue;
        if (st[a][b]) continue;
        
        st[a][b] = true;
        
        PII t = match[a][b];
        if (t.x == 0 || find(t.x, t.y)) {
            match[a][b] = {x, y};
            return true;
        }
    }
    return false;
}

int main() {
    cin >> n >> m >> k;
    
    for (int i = 0; i < k; ++i) {
        int x, y;
        cin >> x >> y;
        g[x][y] = true;
    }
    
    int res = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (g[i][j] || (i + j) % 2) continue;
            memset(st, 0, sizeof st);
            if (find(i, j)) res++;
        }
    }
    
    cout << n * m - k - res << endl;
    
    return 0;
}

题目5379捉迷藏

C++代码如下,

cpp 复制代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 210, M = 30010;

int n, m;
bool d[N][N], st[N];
int match[N];

bool find(int x) {
    for (int i = 1; i <= n; ++i) {
        if (d[x][i] && !st[i]) {
            st[i] = true;
            int t = match[i];
            if (t == 0 || find(t)) {
                match[i] = x;
                return true;
            }
        }
    }
    return false;
}

int main() {
    scanf("%d%d", &n, &m);
    while (m--) {
        int a, b;
        scanf("%d%d", &a, &b);
        d[a][b] = true;
    }
    
    //传递闭包
    for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                d[i][j] |= d[i][k] & d[k][j];
            }
        }
    }
    
    int res = 0;
    for (int i = 1; i <= n; ++i) {
        memset(st, 0, sizeof st);
        if (find(i)) res++;
    }
    
    printf("%d\n", n - res);
    
    return 0;
}

3 参考

染色法判断二分图
匈牙利算法求最大匹配

相关推荐
Q8137574601 小时前
中阳视角下的资产配置趋势分析与算法支持
算法
yvestine1 小时前
自然语言处理——文本表示
人工智能·python·算法·自然语言处理·文本表示
GalaxyPokemon1 小时前
LeetCode - 148. 排序链表
linux·算法·leetcode
iceslime2 小时前
旅行商问题(TSP)的 C++ 动态规划解法教学攻略
数据结构·c++·算法·算法设计与分析
aichitang20243 小时前
矩阵详解:从基础概念到实际应用
线性代数·算法·矩阵
OpenCSG3 小时前
电子行业AI赋能软件开发经典案例——某金融软件公司
人工智能·算法·金融·开源
dfsj660114 小时前
LLMs 系列科普文(14)
人工智能·深度学习·算法
薛定谔的算法5 小时前
《盗梦空间》与JavaScript中的递归
算法
kaiaaaa5 小时前
算法训练第十一天
数据结构·算法
?!7145 小时前
算法打卡第18天
c++·算法