Bipartite Graph-Coloring Method and Hungarian Algorithm

Bipartite graph: n-order undirected graph G is a bipartite graph if and only if there is no odd cycle in G.

Staining method

Idea: Defined by a bipartite graph. For each edge in the graph, its endpoints are in different sets. Therefore, for each fast connection in the graph, you can use dfs to mark each point in the graph. If there are contradictory points, the graph Not a bipartite graph. Time complexity is O(n+M).

#include <iostream>
#include <cstring>

using namespace std;

const int N = 100010, M = 200010;
int e[M], ne[M], h[N], idx;
int color[N];
int n, m;

void add(int a, int b)
{
    
    
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

bool dfs(int now, int c)
{
    
    
    color[now] = c;
    for(int i = h[now]; i != -1; i = ne[i])
    {
    
    
        int j = e[i];
        if(color[j] == c) return false; 
        if(!color[j] && !dfs(j, -c)) return false;   
    }  
    return true;
}

int main()
{
    
    
    memset(h, -1, sizeof h);
    cin >> n >> m;
    
    int a, b;
    for(int i = 0; i < m; i++)
    {
    
    
        cin >> a >> b;
        add(a, b);
        add(b, a);
    }
    
    bool flag = true;
    for(int i = 1; i <= n; i++)
    {
    
    
        if(!color[i] && !dfs(i, 1)) 
        {
    
    
            flag = false;
            break;
        }
    }
    
    if(flag) cout << "Yes";
    else cout << "No";
    
    return 0;
}

Hungary algorithm

Idea:
For the v1 and v2 point sets of the bipartite graph, if you want the maximum number of matching edges, you can use an adjacency table to store the points of v2 that each point of v1 can access, and use an array to store the points of v1 that each point of v2 currently matches. . Traverse each v1 point. If the point in the v2 set found is not occupied, use it. If it is already occupied, see if the point in the v1 set that occupies the point can be changed. Time complexity O(nm).
Note: An array must be used to record whether the v2 point is accessed, otherwise there may be multiple points in v1 "competing" for a certain point in v2, resulting in an endless loop.

#include <iostream>
#include <cstring>
using namespace std;
const int N = 510, M = 100010;
int h[N], e[M], ne[M], idx; // 用链表记录左半部分各点所能到达的点
int match[N]; // 记录右半部分各点所匹配到左半部分的点
bool vis[N]; // 用于判断左边点是否被访问,反正某点被重复改变出现死循环
int n1, n2, m;

void add(int a, int b)
{
    
    
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

bool find(int x)
{
    
    
    for(int i = h[x]; i != -1; i = ne[i])
    {
    
    
        int j = e[i];
        if(!vis[j])
        {
    
    
            vis[j] = true;
            if(!match[j] || find(match[j]))
            {
    
    
                match[j] = x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    
    
    memset(h, -1, sizeof h);
    cin >> n1 >> n2 >> m;

    int l, r;
    for (int i = 0; i < m; i++)
    {
    
    
        cin >> l >> r;
        add(l, r);
    }
    
    int ans = 0;

    for(int i = 1; i <= n1; i++)
    {
    
    
        memset(vis, false, sizeof vis);
        if(find(i)) ans++;
    }

    cout << ans;
    return 0;
}

Guess you like

Origin blog.csdn.net/PBomb/article/details/107774631