思路:二分图水题
分析:只要建模然后套模板ok
代码:
/*DFS求二分图的最大匹配*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 110
int T;
int Nx , Ny , e;/*Nx Ny分别表示的是左右两边的最大的集合的个数*/
int G[MAXN][MAXN];
int Mx[MAXN] , My[MAXN];/*Mx , My分别表示的是左右两边是否和另一边相连的点的编号*/
bool mark[MAXN];/*标记右边的点是否被匹配过*/
/*查找增广路*/
bool FindPath(int u){
/*枚举所有的右边集合的点*/
for(int i = 1 ; i <= Ny ; i++){
if(G[u][i] && !mark[i]){
mark[i] = true;
if(My[i] == -1 || FindPath(My[i])){
/*互换*/
My[i] = u;
Mx[u] = i;
return true;
}
}
}
return false;
}
/*求最大的匹配*/
int MaxMatch(){
int cnt = 0;
memset(Mx , -1 , sizeof(Mx));/*左边集合初始话为空*/
memset(My , -1 , sizeof(My));/*右边集合初始化为空*/
/*每一次都找左边一个未匹配的点进行找增广路*/
for(int i = 1 ; i <= Nx ; i++){
if(Mx[i] == -1){
memset(mark , 0 , sizeof(mark));/*每次的进行初始化mark数组*/
if(FindPath(i))/*找到了增广路则cnt++*/
cnt++;
}
}
return cnt;
}
int main(){
int a , b;
scanf("%d" , &T);
for(int i = 1 ; i <= T ; i++){
scanf("%d%d%d" , &Nx , &Ny , &e);
/*建模*/
for(int j = 1 ; j <= Nx ; j++){
for(int k = 1 ; k <= Ny ; k++)
G[j][k] = 1;
}
for(int j = 0 ; j < e ; j++){
scanf("%d%d" , &a , &b);
G[a][b] = 0;
}
printf("Case %d: %d\n" , i , MaxMatch());
}
return 0;
}
/*BFS找二分图最大匹配*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1010
int T;
int Nx , Ny;/*左边集合和右边集合*/
int G[MAXN][MAXN];/*存储关系的矩阵*/
int Mx[MAXN] , My[MAXN];/*左边和右边点和另外边相连的编号*/
int pre[MAXN] , Q[MAXN];
int mark[MAXN];
int MaxMatch(){
int ans = 0;
int front , rear;
/*把左边和右边集合置为空*/
memset(Mx , -1 , sizeof(Mx));
memset(My , -1 , sizeof(My));
memset(mark , -1 , sizeof(mark));
for(int i = 1 ; i <= Nx ; i++){
if(Mx[i] == -1){
front = rear = 0;
Q[rear++] = i;
pre[i] = -1;
bool flag = 0;
while(front < rear && !flag){
int u = Q[front];
for(int v = 1 ; v <= Ny && !flag ; v++){
if(G[u][v] && mark[v] != i){
mark[v] = i;
Q[rear++] = My[v];
if(My[v] >= 0)
pre[My[v]] = u;
else{
flag = 1;
int d = u , e = v;
while(d != -1){
int t = Mx[d];
Mx[d] = e;
My[e] = d;
d = pre[d];
e = t;
}
}
}
}
front++;
}
if(Mx[i] != -1)
ans++;
}
}
return ans;
}
int main(){
int a , b , e;
scanf("%d" , &T);
for(int i = 1 ; i <= T ; i++){
scanf("%d%d%d" , &Nx , &Ny , &e);
/*建模*/
for(int j = 1 ; j <= Nx ; j++){
for(int k = 1 ; k <= Ny ; k++)
G[j][k] = 1;
}
for(int j = 0 ; j < e ; j++){
scanf("%d%d" , &a , &b);
G[a][b] = 0;
}
printf("Case %d: %d\n" , i , MaxMatch());
}
return 0;
}