二分图匈牙利模板

Posted 抓不住Jerry的Tom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图匈牙利模板相关的知识,希望对你有一定的参考价值。

题目描述

一个矩形可以划分成M*N个小正方形,其中有一些小正方形不能使用。一个多米诺骨牌占用两个相邻的小正方形。试问整个区域内最多可以不重叠地放多少个多米诺骨牌且不占用任何一个被标记为无法使用的小正方形。

输入

第一行有两个用空格隔开的正整数M和N(M<=50,N<=50)。
第二行有一个正整数K,表示共有K个小正方形不能使用。输入数据保证K<=M*N。
以下K行每行有两个用空格隔开的数X和Y,表示第X行的第Y个小正方形不能使用。

输出

输出最多能放多少个多米诺骨牌。

样例输入

3 3
2
1 1
2 2

样例输出

3

  1 #include <bits/stdc++.h>
  2  
  3 using namespace std;
  4 const int maxn = 55;
  5 const int maxm = 3000;
  6 int n,m,k;
  7 int vis[maxm],Left[maxm];
  8 int mark[maxn][maxn];
  9 bool ok[maxn][maxn];
 10 int id[maxn][maxn];
 11 vector<int> l[maxm];
 12 set<int>up;
 13 int getid (int xx,int yy)
 14 {
 15     return (xx-1)*m+yy;
 16 }
 17 bool check (int xx,int yy)
 18 {
 19     if (xx>=1&&xx<=n&&yy>=1&&yy<=m&&ok[xx][yy])
 20         return true;
 21     else
 22         return false;
 23 }
 24 void add (int x,int y)
 25 {
 26     l[x].push_back(y);
 27     l[y].push_back(x);
 28 }
 29 int dfs (int x)
 30 {
 31     for (int i=0;i<l[x].size();++i){
 32         int it = l[x][i];
 33         if(Left[it]==-1){
 34             Left[it] = x;
 35             return 1;
 36         }
 37         if (vis[it]) continue;
 38         vis[it] = 1;
 39         if(dfs(Left[it])){
 40             Left[it] = x;
 41             return 1;
 42         }
 43     }
 44     return 0;
 45 }
 46  
 47 int main()
 48 {
 49     //freopen("de.txt","r",stdin);
 50     while (~scanf("%d%d",&n,&m)){
 51     memset(ok,true,sizeof ok);
 52     memset(Left,-1,sizeof Left);
 53     scanf("%d",&k);
 54     for (int i=0;i<k;++i){
 55         int xx,yy;
 56         scanf("%d%d",&xx,&yy);
 57         ok[xx][yy] = false;
 58     }
 59     for (int i=1;i<=n;++i){
 60         int j;
 61         if (i%2) j=1;
 62         else j=2;
 63         for (;j<=m;j+=2){
 64             if (check(i,j)){
 65                 //printf("%d %d\n",i,j);
 66                 int id = getid(i,j);
 67                 if (check(i+1,j)){
 68                     int id2 = getid(i+1,j);
 69                     add(id,id2);
 70                 }
 71                 if (check(i,j+1)){
 72                     int id2 = getid(i,j+1);
 73                     add(id,id2);
 74                 }
 75                 if (check(i-1,j)){
 76                     int id2 = getid(i-1,j);
 77                     add(id,id2);
 78                 }
 79                 if (check(i,j-1)){
 80                     int id2 = getid(i,j-1);
 81                     add(id,id2);
 82                 }
 83             }
 84         }
 85     }
 86     int ans = 0;
 87     for (int i=1;i<=n;++i){
 88         int j;
 89         if (i%2) j=1;
 90         else j=2;
 91         for (;j<=m;j+=2){
 92             if (check(i,j)){
 93                 memset(vis,0,sizeof vis);
 94                 int id = getid(i,j);
 95                 ans += dfs(id);
 96             }
 97         }
 98     }
 99     printf("%d\n",ans);
100     }
101     return 0;
102 }

 

以上是关于二分图匈牙利模板的主要内容,如果未能解决你的问题,请参考以下文章

二分图匈牙利算法模板

二分图匹配——匈牙利算法

P3386 模板二分图匹配(匈牙利&最大流)

861. 二分图的最大匹配(匈牙利算法模板)

二分图的判定(染色法)和二分图最大匹配(匈牙利)算法及模板

匈牙利 算法&模板