二分图匹配(匈牙利算法模板)

一、最大匹配——匈牙利算法

/****************************************************
二分图匹配(匈牙利算法的DFS实现)
INIT:g[][]两边定点划分的情况
CALL:res=hungary();输出最大匹配数
优点:适于稠密图,DFS找增广路快,实现简洁易于理解
时间复杂度:O(VE);
***************************************************
*/
const int MAXN=1000;
int uN,vN; //u,v数目
int g[MAXN][MAXN];//编号是0~n-1的
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
int v;
for(v=0;v<vN;v++)
if(g[u][v]&&!used[v])
{
used[v]
=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]
=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
int u;
memset(linker,
-1,sizeof(linker));
for(u=0;u<uN;u++)
{
memset(used,
0,sizeof(used));
if(dfs(u)) res++;
}
return res;
}

简单例子:

HDU 2063过山车

#include<stdio.h>

#include<string.h>

const int MAXN=510;

int uN,vN;  //u,v数目

int g[MAXN][MAXN];//编号是0~n-1

int linker[MAXN];

bool used[MAXN];

bool dfs(int u)

{

    int v;

    for(v=1;v<=vN;v++)

        if(g[u][v]&&!used[v])

        {

            used[v]=true;

            if(linker[v]==-1||dfs(linker[v]))

            {

                linker[v]=u;

                return true;

            }   

        } 

    return false; 

}   

int hungary()

{

    int res=0;

    int u;

    memset(linker,-1,sizeof(linker));

    for(u=1;u<=uN;u++)

    {

        memset(used,0,sizeof(used));

        if(dfs(u))  res++;

    }

    return res;  

} 

int main()

{

    int k;

    int u,v;

    while(scanf("%d",&k),k)

    {

        scanf("%d%d",&uN,&vN);

        memset(g,0,sizeof(g));

        while(k--)

        {

            scanf("%d%d",&u,&v);

            g[u][v]=1;

        }

        printf("%d\n",hungary());  

    } 

    return 0; 

} 

 

例:HDU 1045 Fire Net

/*

HDU 1045

*/

#include<stdio.h>

#include<string.h>

#include<iostream>

using namespace std;

int uN,vN;

int g[20][20];

int linker[20];

bool used[20];

char map[5][5];

int mapr[5][5];

int mapl[5][5];

bool dfs(int u)

{

    int v;

    for(v=1;v<=vN;v++)

        if(g[u][v]&&!used[v])

        {

            used[v]=true;

            if(linker[v]==-1||dfs(linker[v]))

            {

                linker[v]=u;

                return true;

            }   

        }

    return false;  

} 

int hungary()

{

    int res=0;

    int u;

    memset(linker,-1,sizeof(linker));

    for(u=1;u<=uN;u++)

    {

        memset(used,0,sizeof(used));

        if(dfs(u))  res++;

    }  

    return res;

} 

int main()

{

    int i,j,n;

    while(scanf("%d",&n),n)

    {

        memset(mapl,0,sizeof(mapl));

        memset(mapr,0,sizeof(mapr));

        memset(g,0,sizeof(g));

        for(i=1;i<=n;i++)

           for(j=1;j<=n;j++)

           {

               cin>>map[i][j];

               if(map[i][j]=='X')

                  mapl[i][j]=mapr[i][j]=-1;

           } 

           int p1=0;

           uN=0;vN=0;

           //给行编号

           for(i=1;i<=n;i++)

              for(j=1;j<=n;j++)

              {

                  while(mapr[i][j]==-1&&j<=n)

                      j++;

                  p1++;

                  while(mapr[i][j]!=-1&&j<=n)

                  {

                      mapr[i][j]=p1;

                      if(uN<p1)  uN=p1;

                      j++;

                  }   

              }

          int p2=0;

          //给列编号

          for(j=1;j<=n;j++)

             for(i=1;i<=n;i++)

             {

                 while(mapl[i][j]==-1&&i<=n)

                      i++;

                  p2++;

                  while(mapl[i][j]!=-1&&i<=n)

                  {

                      mapl[i][j]=p2;

                      if(vN<p2)  vN=p2;

                      i++;

                  }   

             }

         //建图

         for(i=1;i<=n;i++)

            for(j=1;j<=n;j++)

            {

                if(mapr[i][j]!=-1&&mapl[i][j]!=-1)

                  g[mapr[i][j]][mapl[i][j]]=1;

            }

         printf("%d\n",hungary());           

    }

    return 0;   

}

你可能感兴趣的:(二分图)