一、最大匹配——匈牙利算法
/****************************************************
二分图匹配(匈牙利算法的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;
}