思路:二分图水题
分析:只要建模然后套模板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; }
时间: 2024-11-03 21:57:39