Matching of bipartite graphs-Hungarian algorithm

What is matching

Matching : In graph theory, a "matching" is a set of edges, in which any two edges have no common vertices.
Maximum match : Among all matches in a graph, the match with the most matching edges is called the maximum match of this graph.

Matching of bipartite graph : Given a bipartite graph G, in a subgraph M of G, any two edges in the edge set {E} of M are not attached to the same vertex, then M is said to be a match.
Maximum matching of a bipartite graph : A group of matches containing the most edges among all matches is called the maximum matching of a bipartite graph, and the number of edges is the maximum number of matches.

Hungary algorithm

The previous coloring method is to judge whether a graph is a bipartite graph; the
Hungarian algorithm is an algorithm for finding the maximum matching of a bipartite graph based on the bipartite graph.

The bipartite graph divides the vertices into two sets A and B. There are no edges between sets A and B, and there are edges between points in A and B. (There is an edge between the point x in A and some points in B, there may be one, there may be multiple, or there may be no.) The
maximum matching is to choose as many edges as possible, so that the points in A and the points in B Matching, and only one-to-one matching, that is, the matched ones cannot be matched again, so that any two edges have no common vertices.

Bipartite graphs are generally undirected graphs, Two-way matching, we try to match when the only match on the line from one direction to the other: The following codes are hypothetical and do questions from set A to set B Zone match . Therefore, although it is an undirected graph, we can only store the edges from A->B , but not the edges from B->A, so that the vertices can be automatically divided into two sets, and the numbers of the nodes in the two sets All can start from 1 .

Matching process

If the girl you are looking for already has a boyfriend,
you can ask her boyfriend
if you have a spare tire.
Can you give this to me? If
he can let it go,
if he can't let it , they are true love.
You look for your next spare tire.

Suppose there is a temporary matching relationship a1----b1, a2----b2 at this time, the vertex a1 in A has points pointing to b1, b2, a2 ​​has only edges pointing to b2, and a3 has points to b1, b3, etc. For the edge of ……, we take the matching of vertex a3 in A as an example:

Assuming that there is a matching relationship a1----b1, a2----b2 temporarily, then a2 cannot have an edge pointing to b1, otherwise it does not conform to the Hungarian algorithm core 1.

The following analysis process:

Find a matching object for a3. A3 first finds b1 and finds that b1 has been matched, but at this time a3 is not looking for b3, but asks b1 to find his matching object a1, and see if a1 can find other points to match , At this time back to the problem of finding a matching object for a1 , but the matching object b1 is banned , so a1 can no longer find b1, and then go to b2, b2 is not banned, you can find it, but b2 already has a matching object a2, and then ask if a2 can change a matching object. At this time, it is back to the problem of finding a matching object for a2 . At the same time, points b1 and b2 are banned , because point b1 is what point a3 wants, b2 Point is what point a1 wants, and it’s all pending ,But a2 has no choice to go back, At this time a2 and b2 are true love, they are permanently matched and locked . Then go back and tell a1, b2 is no good, you can find the next one, but a1 also has no room for retreat , so a1 and b1 are also true love, permanently matched and locked. Then tell a3, b1 is no good, you can find the next one, and then a3 starts to find b3...

The above matching can match the array, a prohibited state may be represented st array, the array is locked can be represented vis
match[j]=ia point representing the point i j in set A and set B is temporarily matching
st[j]=trueof vertices j temporarily disabled
vis[j]=truerepresents match[i]=jthe i And j is true love. Don’t think about the vertex j for the vertices that come later.

Suppose that a1 has only edges pointing to b1 and b2, a2 ​​has only edges pointing to b1, b2, and a3 has edges pointing to b1, b2, and b3.
First select a1, match[a1]=b1;
then select a2, and find that b1 is occupied. Then force a1 to give way. At this time, match[a1]=b2; match[a2]=b1;
Then a3 selects , b1 is occupied, and then a3 forces a2 to give way . A2 cannot choose b1, but can only choose b2, then a2 Forcing a1 to give way. At this time, a1 cannot choose b1 and b2. A1 has no room for retreat. A1 and b2 are locked. After telling the message to a2, a2 ​​has no room for retreat, and a2 and b1 are locked.
When a3 finds b2, tell a3 directly, b2 is locked, no show, you can find the next one.
Next, a3 finds b3, there is match[a3]=b3;

Another example is to illustrate the core of the Hungarian algorithm:

  1. The first match is temporary, and the second match is the most likely to be obtained, because the first match must be matched as far as possible, unless the first matchyieldTo the point where there is no retreat.
  2. This is a recursive process. The match at the end of the recursion is not just because the vertex of this match has a degree of 1, and only one edge extends to another set . This is just one of the cases. The general situation is this vertex. I have reached the point where I can't retreat, I can't give any more to other apexes, and let myself be gone.

Title description

Given a bipartite graph, the left half of the set contains n1 points ( number 1-n1 ), the right half of the set contains n2 points ( number 1-n2 ), the bipartite graph contains a total of m edges.

The data guarantees that the two end points of any edge cannot be in the same part.

Please find the maximum number of matches of the bipartite graph.

Input format The
first line contains three integers n1, n2, and m.

In the next m rows, each row contains two integers u and v, indicating that there is an edge between the point u in the left half of the point set and the point v in the right half of the point set.

Output format
Output an integer, which represents the maximum number of matches of the bipartite graph.

Data range
1≤n1,
n2≤500,
1≤u≤n1,
1≤v≤n2 , 1≤m≤10 5

Input sample:

2 2 4
1 1
1 2
2 1
2 2

Sample output:

2

Algorithm implementation

#include <iostream>
#include <cstring>

using namespace std;

#define read(x) scanf("%d",&x)
const int N=510,M=1e5+10;  //虽是无向图,但是存储单方向的边A->B即可,到时候从A找点匹配B
int h[N],e[M],ne[M],idx;
int match[N]; 
bool vis[N],st[N];
//三个数组维护的含义见上面或下面
int n1,n2,m;
"n1+n2是总顶点数,n1是A集合中顶点数,n2是B集合中顶点数,由题目要求限制"

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

int find(int v)
{
    
    
    for (int i=h[v];~i;i=ne[i]) {
    
    
        int j=e[i];
        if (!vis[j] && !st[j]) {
    
    
            if (match[j]==0) {
    
    match[j]=v; return true;}
            else {
    
    
                st[j]=true;
                if (find(match[j])) {
    
    match[j]=v; return true;}
                else vis[j]=true;
            }//此时说明B堆中的j结点与A堆中的结点match[j]是板上钉钉的匹配了,不能再改了,
        }    //所以后面的点再匹配就不用再找我了,
    }
    return false;
}

int main()
{
    
    
    memset(h,-1,sizeof h);
    read(n1),read(n2),read(m);//A堆顶点数n1,B堆顶点数n2,边数m
    int a,b;
    while (m--) {
    
    
        read(a),read(b);
        add(a,b);"两个堆中结点编号重复,这里无影响,也可以add(a,n1+b);"
    }
    int res=0; //统计最大匹配的边数
    for (int i=1;i<=n1;i++) {
    
    
        memset(st,false,sizeof st); //每次初始化一下st数组,重新禁止一些匹配。
        if(find(i)) res++; 
    }
    printf("%d",res);
    
    return 0;
}

match array:
Traverse the A heap and store the edges of A->B. At this time, match[i]=j; means that the vertex i in the B pile matches the vertex j in the A pile. Since the subscripts of the vertices in the graph all start from 1, when match[i]=0, it means No match yet.

st array:
The function of the st array is that when a left point matches a point that already has an object on the right, the right point corresponds to the left point of the side to find a new "object", no more To find the point on the right of the original, due to multiple recursions, the prohibited points before each recursion must be recorded, so an st array is created, and every time a new match is started, the st array must be reset to false, and then recursively. Prohibit

vis array: The
vis array is used to record the points that are not selected in the B heap. When the point in the B heap only matches the point in the A heap, it is locked, so it does not find ( It is necessary to match[ ]).

In the primary version, I want to use match[j]!=x in if (!vis[j] && match[j]!=x) to replace the function of the st array, but because each recursion will prohibit a j, and this is only The current j will be banned, and it will have no effect on the previous j, which will easily cause an endless loop. Burst stack.

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

The judgment on line 5 is different, which is wrong.

Guess you like

Origin blog.csdn.net/HangHug_L/article/details/114106714