zoukankan      html  css  js  c++  java
  • uva11419 二分图--最小覆盖=最大匹配

    大白书355

     1 // UVa11419 SAM I AM
     2 // Rujia Liu
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <vector>
     6 #include <algorithm>
     7 using namespace std;
     8 
     9 const int maxn = 1000 + 5; // 单侧顶点的最大数目
    10 
    11 // 二分图最大基数匹配
    12 struct BPM {
    13   int n, m;               // 左右顶点个数
    14   vector<int> G[maxn];    // 邻接表
    15   int left[maxn];         // left[i]为右边第i个点的匹配点编号,-1表示不存在
    16   bool T[maxn];           // T[i]为右边第i个点是否已标记
    17 
    18   int right[maxn];        // 求最小覆盖用
    19   bool S[maxn];           // 求最小覆盖用
    20 
    21   void init(int n, int m) {
    22     this->n = n;
    23     this->m = m;
    24     for(int i = 0; i < n; i++) G[i].clear();
    25   }
    26 
    27   void AddEdge(int u, int v) {
    28     G[u].push_back(v);
    29   }
    30 
    31   bool match(int u){
    32     S[u] = true;
    33     for(int i = 0; i < G[u].size(); i++) {
    34       int v = G[u][i];
    35       if (!T[v]){
    36         T[v] = true;
    37         if (left[v] == -1 || match(left[v])){
    38           left[v] = u;
    39           right[u] = v;
    40           return true;
    41         }
    42       }
    43     }
    44     return false;
    45   }
    46 
    47   // 求最大匹配
    48   int solve() {
    49     memset(left, -1, sizeof(left));
    50     memset(right, -1, sizeof(right));
    51     int ans = 0;
    52     for(int u = 0; u < n; u++) { // 从左边结点u开始增广
    53       memset(S, 0, sizeof(S));
    54       memset(T, 0, sizeof(T));
    55       if(match(u)) ans++;
    56     }
    57     return ans;
    58   }
    59 
    60   // 求最小覆盖。X和Y为最小覆盖中的点集
    61   int mincover(vector<int>& X, vector<int>& Y) {
    62     int ans = solve();
    63     memset(S, 0, sizeof(S));
    64     memset(T, 0, sizeof(T));
    65     for(int u = 0; u < n; u++)
    66       if(right[u] == -1) match(u); // 从所有X未盖点出发增广 如果他没有找到匹配对象说明X方向的小于Y方向的,显然Y的个数才是此时的最小匹配
    67     for(int u = 0; u < n; u++)
    68       if(!S[u]) X.push_back(u); // X中的未标记点
    69     for(int v = 0; v < m; v++)
    70       if(T[v]) Y.push_back(v);  // Y中的已标记点
    71    return ans;
    72   }
    73 };
    74 
    75 BPM solver;
    76 
    77 int R, C, N;
    78 
    79 int main(){
    80   int kase = 0;
    81   while(scanf("%d%d%d", &R, &C, &N) == 3 && R && C && N) {
    82     solver.init(R, C);
    83     for(int i = 0; i < N; i++) {
    84       int r, c;
    85       scanf("%d%d", &r, &c); r--; c--;
    86       solver.AddEdge(r, c);
    87     }
    88     vector<int> X, Y;
    89     int ans = solver.mincover(X, Y);
    90     printf("%d", ans);
    91     for(int i = 0; i < X.size(); i++) printf(" r%d", X[i]+1);
    92     for(int i = 0; i < Y.size(); i++) printf(" c%d", Y[i]+1);
    93     printf("
    ");
    94   }
    95   return 0;
    96 }
  • 相关阅读:
    bzoj1966:[AHOI2005]病毒检测
    bzoj2938:[Poi2000]病毒
    bzoj3172:[Tjoi2013]单词
    luoguP3808[模板]AC自动机(简单版)
    luoguP3796[模板]AC自动机(加强版)
    Java 基本类型、封装类型、常量池、基本运算
    Java 内存分配(转)
    Java 数组ArrayList语法
    Java的修饰、继承、接口、抽象类
    2019数模国赛有感
  • 原文地址:https://www.cnblogs.com/Opaser/p/4376329.html
Copyright © 2011-2022 走看看