FZU 2039 pets

简介: 点击打开链接FZU2039 思路:二分图水题 分析:只要建模然后套模板ok 代码: /*DFS求二分图的最大匹配*/#include#include#include#includeusing namespace std;...

点击打开链接FZU2039


思路:二分图水题
分析:只要建模然后套模板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;
}






目录
相关文章
|
人工智能 Java
2021杭电多校5-Arrary-hdu7020
Array Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Total Submission(s): 965 Accepted Submission(s): 312 Problem Description Given an integer array a[1…n].
137 0
2021杭电多校5-Arrary-hdu7020
|
算法 Java
HDU 2084 数塔
在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
148 0
FZU 2167 大王叫我来巡山呐
Problem 2167 大王叫我来巡山呐 Accept: 931    Submit: 1405Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description   大师兄在取得真经后,每天详读经书,认真完成读书笔记,理论联系实际,不断提高实践能力。
913 0