hopcroft-karp算法用于二分图最大匹配,是匈牙利算法的改进,做法是一次处理多条增广路径,而不是像匈牙利算法一样找到一条处理一条,这样时间复杂度可以改进为O(sqrt(n)*m)
模板:
对应的题目是POJ-1469
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int maxn=500+50;
const int INF=0x3f3f3f3f;
vector<int>G[maxn];
int uN;//左端点个数
int Mx[maxn],My[maxn];
int dx[maxn],dy[maxn];
int dis;
bool used[maxn];
void init()
{
for(int i=0;i<maxn;i++)G[i].clear();
}
bool searchP()
{
queue<int>Q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=0;i<uN;i++)
{
if(Mx[i]==-1)
{
Q.push(i);
dx[i]=0;
}
}
while(!Q.empty())
{
int u=Q.front();Q.pop();
if(dx[u]>dis)break;
int sz=G[u].size();
for(int i=0;i<sz;i++)
{
int v=G[u][i];
if(dy[v]==-1)
{
dy[v]=dx[u]+1;
if(My[v]==-1)
dis=dy[v];
else
{
dx[My[v]]=dy[v]+1;//v匹配的点的距离=v的距离+1
Q.push(My[v]);
}
}
}
}
return dis!=INF;
}
bool DFS(int u)
{
int sz=G[u].size();
for(int i=0;i<sz;i++)
{
int v=G[u][i];
if(!used[v]&&dy[v]==dx[u]+1)//沿着增广路dfs
{
used[v]=true;
if(My[v]!=-1&&dy[v]==dis)continue;
if(My[v]==-1||DFS(My[v]))//找到了对应的增广路
{
My[v]=u;
Mx[u]=v;
return true;
}
}
}
return false;
}
int Maxmatch()
{
int res=0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(searchP())//找到增广路
{
memset(used,false,sizeof(used));
for(int i=0;i<uN;i++)
{
if(Mx[i]==-1&&DFS(i))
res++;
}
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int nx,ny;
scanf("%d%d",&nx,&ny);
uN=nx;
for(int i=0;i<nx;i++)
{
int snum;
scanf("%d",&snum);
int u;
for(int j=0;j<snum;j++)
{
scanf("%d",&u);
u+=nx;
G[i].push_back(u);
G[u].push_back(i);
}
}
if(Maxmatch()==nx)
puts("YES");
else
puts("NO");
}
return 0;
}