二分图匹配模板

二分图匹配:

知识点:交替路,增广路,匈牙利树,匈牙利算法求最大匹配数,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;
}

 

全部评论

相关推荐

ArisRobert:统一解释一下,第4点的意思是,公司按需通知员工,没被通知到的员工是没法去上班的,所以只要没被通知到,就自动离职。就是一种比较抽象的裁员。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务