【算法复习】codevs1022 匈牙利算法

时间:2022-04-20 11:34:04
题目描述 Description

有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。

【算法复习】codevs1022 匈牙利算法

输入描述 Input Description

输入文件的第一行是两个整数NM  (1<=NM<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N1<=Y<=M)。

输出描述 Output Description

输出所覆盖的最大面积块(1×2面积算一块)。

样例输入 Sample Input

4 4

6

1 1

1 4

2 2

4 1

4 2

4 4

样例输出 Sample Output

4

【题解】普通二分图匹配,黑白染色

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
const int m1[]={,,,-},m2[]={,-,,};
int n,m,k,a[][],cnt[],tag[][],c[][],all,used[],girl[];
inline bool find(int h){
for(int i=;i<=cnt[];i++)
if(c[h][i]==true&&used[i]==false){
used[i]=true;
if(girl[i]==||find(girl[i])){
girl[i]=h;
return true;
}
}
return false;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=,x,y;i<=k;i++){
scanf("%d%d",&x,&y);
a[x][y]=;
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(!a[i][j]){
cnt[(i+j)&]++;
tag[i][j]=cnt[(i+j)&];
}
for(int i=;i<=n;i++)
for(int j=,x,y;j<=m;j++){
if((!a[i][j])&&(i+j)%==){
for(int k=;k<;k++){
x=i+m1[k];y=j+m2[k];
if(!(<=x&&x<=n&&<=y&&y<=m)) continue;
if(!a[x][y]){
c[tag[i][j]][tag[x][y]]=;
}
}
}
}
for(int i=;i<=cnt[];i++){
memset(used,false,sizeof(used));
if(find(i)) all++;
}
cout<<all<<endl;
return ;
}

当然,比赛的时候谁会去写这玩意啊