匈牙利:
bool find(int u)
{
flag[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!flag[v])
{
flag[v]=1;
if(match[v]==0||find(match[v]))
{
match[v]=u;
return true;
}
}
}
return false;
}
int function()
{
int ans=0;
memset(match,0,sizeof(match));
for(int i=1;i<=n;i++)
{
memset(flag,0,sizeof(flag));
if(find(i))ans++;
}
return ans;
}
km:
bool dfs(int s) //匈牙利算法找增广路径
{
visx[s]=1;
for(int i=1;i<=cnty;i++)
if(!visy[i]){
int t=wx[s]+wy[i]-dis[s][i];
if(t==0) {
visy[i]=1;
if(linky[i]==0||dfs(linky[i])){
linkx[s]=i,linky[i]=s;
return true;
}
}
else if(t>0) //找出边权与顶标和的最小的差值
{
if(t<minz)minz=t;
}
}
return false;
}
void km()
{
memset(linkx,0,sizeof linkx); //linkx[i]表示与X部中点i匹配的点
memset(linky,0,sizeof linky);
for(int i=1;i<=cntx;i++){
while(1){
minz=INF;
memset(visx,0,sizeof visx);
memset(visy,0,sizeof visy);
if(dfs(i))break;
for(int j=1;j<=cntx;j++) //将交错树中X部的点的顶标减去minz
if(visx[j])wx[j]-=minz;
for(int j=1;j<=cnty;j++) //将交错树中Y部的点的顶标加上minz
if(visy[j])wy[j]+=minz;
}
}
}