• 二分图匹配模板


    二分图匹配:

    知识点:交替路,增广路,匈牙利树,匈牙利算法求最大匹配数,bfs染色法判断是否是二分图(不存在奇数回路)

    例题:hud2063 匈牙利算法

     1 #include <iostream>
     2 #include<bits/stdc++.h>
     3 //二分图匹配,在find函数理解。
     4 //找增广路,增广路的定义是从为匹配的节点出发,终止与未匹配的节点,中间是交替路。
     5 //find函数的递归不是一层一层的,而是直接dfs一个节点的匹配的节点
     6 //然后沿着增广路修改相互匹配的节点,在寻找过程中,用vis标记节点是否在增广路中,可以保证找的路线就是交替路,
     7 #include <iostream>
     8 using namespace std;
     9 const int N = 505;
    10 vector<int>ve[2 * N];
    11 bool vis[2 * N];
    12 int match[2 * N];
    13 int k, m, n;
    14 bool find(int u) {
    15     for (int i = 0; i < ve[u].size(); i++) {
    16         int v = ve[u][i];
    17         if (!vis[v]) {//不在交替路中
    18             vis[v] = true;//放入交替路中
    19             if (match[v] == -1 || find(match[v])) {
    20                 //最后找到未匹配的点,说明找到一条增广路。
    21                 //交换路径,返回成功。
    22                 match[v] = u;
    23                 match[u] = v;
    24                 return true;
    25             }
    26         }
    27     }
    28     return false;
    29 }
    30 void count() {
    31     int ans = 0;
    32     for (int i = 1; i <=m + n; i++) {
    33         if (match[i] == -1) {
    34             memset(vis, false, sizeof(vis));
    35             if (find(i))ans++;
    36         }
    37     }
    38     cout << ans << endl;
    39 }
    40 void init() {
    41     for (int i = 0; i < 2 * N; i++) {
    42         ve[i].clear();
    43     }
    44     memset(match, -1, sizeof(match));
    45 }
    46 int main()
    47 {
    48 
    49     int u, v;
    50     while (scanf("%d", &k) && k) {
    51         scanf("%d%d", &m, &n);
    52         init();
    53         for (int i = 0; i < k; i++) {
    54             scanf("%d%d", &u, &v);
    55             ve[u].push_back(v + m);
    56             ve[v + m].push_back(u);
    57         }
    58         count();
    59     }
    60 
    61     return 0;
    62 }

    bfs染色法

    bool bfs()
    {
        queue<int> q;
        bool tag[N];
        //memset(tag,false,sizeof(tag));
        memset(vis,false,sizeof(vis));
        for (int j=1;j<=n;j++) if (!vis[j]) { // 遇到没染色的点就从它出发去染色其它点
            q.push(j);
            tag[j]= vis[j]=true;
            while(!q.empty()){
                int t=q.front();  q.pop();
                for (int i=1;i<=n;i++) if (g[t][i] && i!=t)
                {
                    if (vis[i]){
                        if (tag[i]==tag[t]) return false;
                    } else{
                       tag[i]=!tag[t];
                       q.push(i);
                       vis[i]=true;
                    }
                }
            }
        }
    
        return true;
    }
    不疯魔不成活
  • 相关阅读:
    hdu5360 Hiking(水题)
    hdu5348 MZL's endless loop(欧拉回路)
    hdu5351 MZL's Border(规律题,java)
    hdu5347 MZL's chemistry(打表)
    hdu5344 MZL's xor(水题)
    hdu5338 ZZX and Permutations(贪心、线段树)
    hdu 5325 Crazy Bobo (树形dp)
    hdu5323 Solve this interesting problem(爆搜)
    hdu5322 Hope(dp)
    Lightoj1009 Back to Underworld(带权并查集)
  • 原文地址:https://www.cnblogs.com/gzr2018/p/10823647.html
Copyright © 2020-2023  润新知