二分图匈牙利模板

题目描述

一个矩形可以划分成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 }
时间: 2024-11-10 08:06:21

二分图匈牙利模板的相关文章

HiHo1121 : 二分图一?二分图判定(模板题)

描述 大家好,我是小Hi和小Ho的小伙伴Nettle,从这个星期开始由我来完成我们的Weekly. 新年回家,又到了一年一度大龄剩男剩女的相亲时间.Nettle去姑姑家玩的时候看到了一张姑姑写的相亲情况表,上面都是姑姑介绍相亲的剩男剩女们.每行有2个名字,表示这两个人有一场相亲.由于姑姑年龄比较大了记性不是太好,加上相亲的人很多,所以姑姑一时也想不起来其中有些人的性别.因此她拜托我检查一下相亲表里面有没有错误的记录,即是否把两个同性安排了相亲. OK,让我们愉快的暴力搜索吧! 才怪咧. 对于拿到

二分图匈牙利算法模板

最大匹配数:最大匹配的匹配边的数目 最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择 最大独立数:选取最多的点,使任意所选两点均不相连 最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径.路径长可以为0(即单个点). 定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理) 定理2:最大匹配数 = 最大独立数 定理3:最小路径覆盖数 = 顶点数 - 最大匹配数 const int N=555;///两边的最大数量 bool tu[N

二分图匹配(模板)

二分图匹配 附上两种方法: 网络流 据说所有的二分图题目都可以用网络流跑过去,可能还快一些 话不多说,只有代码 /* 二分图匹配的题大多可用网络流做 此处为Dinic模板,详见网络流模板 */ #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algo

二分图的模板

博客: 匈牙利算法模板: #include<bits/stdc++.h> #define MAXN 9999 using namespace std; int nx,ny;//nx表示二分图左边顶点的个数,ny表示二分图右边顶点的个数 int m;//m代表边的条数 int cx[MAXN],cy[MAXN];//如果有cx[i]=j,则必有cy[j]=i,说明i点和j点能够匹配 int x,y;//x点到y点有边 int e[MAXN][MAXN];//邻接矩阵 int visited[MA

二分图【模板】

二分图:原图G的顶点可以分类两个集合X和Y,所有的边关联的两个顶点恰好一个属于集合X,另一个属于集合Y,则称该图为二分图. 二分图匹配:给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,即一个顶点最多只有一条边.则称M是一个匹配. 二分图最大匹配:图中包含边数最多的匹配称为图的最大匹配. 二分图完美匹配:如果所有点都在匹配边上,则称这个最大匹配是完美匹配. 二分图多重匹配:二分图匹配一对一匹配,这里允许集合Y中的一个元素和集合X中的多个元素匹配(一般有最大限制N)

hiho1122_二分图匈牙利算法

题目 给定一个图的N个节点和节点之间的M条边,数据保证该图可以构成一个二分图.求该二分图最大匹配. 题目链接:二分图最大匹配     首先通过染色法,将图的N个节点分成两个部分:然后通过匈牙利算法求二分图的最大匹配. 实现 #include<stdio.h> #include<string.h> #include<iostream> #include<string> #include<set> #include<map> #inclu

POJ 3020 Antenna Placement(二分图 匈牙利算法)

题目网址:  http://poj.org/problem?id=3020 题意: 用椭圆形去覆盖给出所有环(即图上的小圆点),有两种类型的椭圆形,左右朝向和上下朝向的,一个椭圆形最多可以覆盖相邻的两个小圆点.   思路: 将每个小圆点看作是一个顶点,因为一个椭圆只能覆盖两个小圆点,我们就可以把这个图看成一个二分图.将相邻的两个点,一个看作是X集合内顶点,另一个看成是Y集合内顶点.但要注意的是一个顶点可能不止和一个顶点想连(如上图情况),所以我们要把上述情况看作是一个无向图,而不是有向图.无向图

二分图 匈牙利算法

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. -------等等,看得头大?那么请看下面的版本: 通过数代人的努力,你终于赶上了剩男剩女的大潮,假设你是一位光荣的新世纪媒人,在你的手上有N个剩男,M个剩女,每个人都可能对多名异性有好感(-_-||暂时不考虑特殊的性取向),如果一对男女互有好感,那么你就可以把这一对撮合在一起,现在

[二分图-匈牙利]poj1422

题意: 给出一个图,伞兵降落到一个点上,然后只能按照一个方向走,问最少降落几个伞兵可以访问完所有的点? 分析: 这是一个最小路径覆盖问题. 最小路径覆盖就是在一个图中用最少的路径可以覆盖所有的点. 在二分图中 最小路径覆盖=点集-最大匹配数 ,对于二分图的最小路径覆盖很好求,那么此题很可惜是一个有向图.不过,可以通过将有向图转化为二分图来求解. 通常的做法是将点i,拆分成i,i',(i,j)变成(i,j'); 那么 那么直接通过匈牙利算法来求出最大匹配就可以解决这个问题了. #include <