二分图匹配练习题

来源:互联网 发布:windows优化大师电脑版 编辑:程序博客网 时间:2024/06/05 00:38

关于二分图匹配的讲解见文章二分图匹配。

本文练习两个简单的二分图匹配,分别对应于文章中的dfs和bfs的Hungary算法。

1、HDU1150 

题意:两台机器A和B,每台都有许多工作模式。有多个任务,每个任务可以在A机器的某个模式或者在B机器的某个模式完成。问最少需要重启几次机器。

分析:该问题即最小点覆盖,即选取最少的点,使任意一条边至少有一个端点被选择,任务相当于边。最小点覆盖数=最大匹配数。

代码(dfs):

#include <stdio.h>#include <string.h>#define N 102int G[N][N];int matching[N], check[N];int n, m, k;bool dfs(int u){    for(int i = 1; i <= m; i++){        if(G[u][i]!=-1 && !check[i]){            check[i] = 1;            if(matching[i] == -1 || dfs(matching[i])){                matching[i] = u;                return true;            }        }    }    return false;}int main(){    while(scanf("%d", &n) && n){        scanf("%d%d", &m, &k);        int a, b, c;        memset(G, -1, sizeof(G));        for(int i = 0; i < k; i++){            scanf("%d%d%d", &a, &b, &c);            if(b && c)                G[b][c] = a;        }        int cnt = 0;        memset(matching, -1, sizeof(matching));        for(int i = 1; i <= n; i++){            memset(check, 0, sizeof(check));            if(dfs(i))                cnt++;        }        printf("%d\n", cnt);    }    return 0;}

2、POJ2446

题意:给一个n*m的表格,表格中有一些格子挖去,用1*2或者2*1的长方形去覆盖,判断是否恰好完全覆盖。

解析:首先需要根据给定的图重新建图,然后求最大匹配数,如果剩余的格子的是最大匹配数的两倍,那么可以完全覆盖。

代码(bfs):

#include <stdio.h>#include <string.h>#include <queue>#include <vector>using namespace std;const int N = 32*32+5;int tol, k;int a[35][35];int pre[N], matching[N], check[N];vector<int>G[N];queue<int> Q;int nt[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};bool Hungary(){int ans = 0;memset(matching, -1, sizeof(matching));memset(check, -1, sizeof(check));for(int i = 1; i <= tol; i++){if(matching[i] == -1){while(!Q.empty())Q.pop();Q.push(i);pre[i] = -1;bool flag = false;while(!Q.empty() && !flag){int u = Q.front();Q.pop();for(int j = 0; j < G[u].size() && !flag; j++){int v = G[u][j];if(check[v] != i){check[v] = i;Q.push(matching[v]);if(matching[v] != -1){pre[matching[v]] = u;}else{flag = true;int d = u, e = v;while(d != -1){int t = matching[d];matching[d] = e;matching[e] = d;d = pre[d];e = t;}}}}}if(matching[i] != -1)ans++;}}if((tol - k) / 2 == ans)return true;return false;}int main(){int x, y, n, m;while(~scanf("%d%d%d", &n, &m, &k)){memset(a, 0, sizeof(a));for(int i = 0; i < k; i++){scanf("%d%d", &y, &x);a[x][y] = 1;}tol = n * m;if((tol - k) % 2){printf("NO\n");continue;}for(int i = 1; i <= tol; i++)G[i].clear();for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++){if(a[i][j] == 1)continue;int nw = (i-1)*m + j;for(int k = 0; k < 4; k++){int nx = i + nt[k][0];int ny = j + nt[k][1];if(nx <= 0 || nx > n || ny <= 0 || ny > m)continue;if(a[nx][ny] == 1)continue;int p = (nx-1)*m + ny;G[nw].push_back(p);}}bool flag = Hungary();if(flag)printf("YES\n");else printf("NO\n");}return 0;}

原创粉丝点击