Hungarian algorithm for bipartite graph matching

PART 1 What is a bipartite graph

Bipartite graph, also known as bipartite graph, is a special model in graph theory. Let G=(V,E) be an undirected graph, if the vertex V can be divided into two mutually disjoint subsets (A,B), and each edge (i,j) in the graph is associated with two Vertices i and j belong to these two different vertex sets (i in A, j in B) respectively, then the graph G is called a bipartite graph.

This graph is a bipartite graph

PART 2 What is bipartite graph matching

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.

Maximal matching means that under the currently completed matching, the number of matching edges cannot be increased by adding unfinished matching edges. The maximum matching is the one with the largest number of edges among all the maximal matchings. Choosing such a subset with the largest number of edges is called the maximum matching problem of the graph.
If in a match, every vertex in the graph is associated with an edge in the graph, the match is called a perfect match, also known as a complete match.
To find the maximum matching of a bipartite graph, you can use Maximal Flow or Hungarian Algorithm
PART 3 Hungarian Algorithm
The main operation of the Hungarian algorithm is to enumerate the points on the left, find the first edge connected to the point on the right, and then if the connected point has been matched with other points, match the previous point with other points connected to it, And keep repeating this operation, if the previous point cannot match other points, the currently enumerated point enumerates its next edge, if all the edges fail, this point does not participate in the matching
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
int g[1100][1100];
int used[1100],wh[1100];
int ans;
int t,n,m;
inline bool work(int now){
    int i,j,k;
    for(j=1;j<=m;j++)
       if(used[j]!=t&&g[now][j]){
           used[j]=t;
           if(!wh[j]||work(wh[j])){
               wh[j]=now;
               return 1;
           }
    }
    return 0;
}
inline void go(){
    int i,j,k;
    for(i=1;i<=n;i++){
        t=i;
        if(work(i))ans++;
    }
}
int main(){
    int i,j,k,x,y;
    cin>>n>>m>>k;
    for(i=1;i<=k;i++){
        cin>>x>>y;
        if(y<=m)
          g[x][y]=1;
    }
    go();
    cout<<ans<<endl;
    return 0;
}
附赠最大流做法代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int inf=1e9+7;
struct edge{
      int c,to,next;
}e[2000000];
int head[5000],level[5000],cnt;
void read(int &x){
      int f=1;x=0;
      char s=getchar();
      while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
      while(s>='0'&&s<='9'){x=x*10+(s-'0');s=getchar();}
      x=(f==1?x:-x);
}
void add(int u,int v,int w){
      e[cnt].c=w;
      e[cnt].to=v;
      e[cnt].next=head[u];
      head[u]=cnt++;
      e[cnt].to=u;
      e[cnt].next=head[v];
      head[v]=cnt++;
}
int bfs(int s,int t){
      queue<int>q;
      memset(level,-1,sizeof(level));
      q.push(s);
      level[s]=0;
      while(!q.empty()){
          int u,v;
          u=q.front();
          q.pop();
          for(int i=head[u];~i;i=e[i].next){
              v=e[i].to;
              if(level[v]==-1&&e[i].c){
                  level[v]=level[u]+1;
                  q.push(v);
                  if(v==t)return 1;
              }
          }
      }
      if(level[t]==-1)return 0;
      return 1;
}
int dfs(int u,int v,int flow){
      if(u==v)return flow;
      int res=0;
      for(int i=head[u];~i;i=e[i].next){
          int j=e[i].to;
          if(level[j]==level[u]+1&&e[i].c){
              int f=dfs(j,v,min(e[i].c,flow-res));
              res+=f;
              e[i].c-=f;
              e[i^1].c+=f;
          }
      }
      if(!res)level[u]=-1;
      return res;
}
int main()
{     int n,m,E,i,j,k,u,v,ans=0;
      read(n);
      read(m);
      read(E);
      memset(head,-1,sizeof(head));
      for(i=1;i<=E;i++){
          read(u);
          read(v);
          if(v>m)continue;
          add(u,v+n,1);
      }
      int s=n+m+1,t=n+m+2;
      for(i=1;i<=n;i++){
         add(s,i,1);
      }
      for(i=1;i<=m;i++){
         add(n+i,t,1);
      }
      while(bfs(s,t))
         ans+=dfs(s,t,inf);
      printf("%d\n",ans);
      return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326529770&siteId=291194637