匈牙利算法模板 时间复杂度为O(VE) V为二分图左边的顶点数,E为二分图中边的数目
#include<stdio.h>
#include<string.h>
const int maxn=1010;
const int maxm=20010;
const int MAX=10001;
const int INF=1000000000;
int line[maxn];
int n,m,cnt,slack;
int head[maxn];
bool used[maxn];//Y集合中点的状态
struct EDGE
{
int u,v,w,next;
}edge[maxm];
void addedge(int u,int v,int w)
{
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;
}
bool find(int u)//寻找增广路
{
for(int e=head[u];e!=-1;e=edge[e].next){//对于所有u->v
int v=edge[e].v;
if(!used[v])//v没有被标记
{
used[v]=true;
if(line[v]==-1||find(line[v])){//v没有匹配或者v有增广路
line[v]=u;
return 1;
}
}
}
return 0;
}
int Hungary()//返回匹配数
{
int all=0;
for (int i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
if(find(i)) all+=1;
}
return all;
}
KM算法模板
#include<stdio.h>
#include<string.h>
const int maxn=1010;
const int maxm=20010;
const int MAX=10001;
const int INF=1000000000;
int lx[maxn],ly[maxn];//顶标
bool visx[maxn],visy[maxn];//开两个数组是需要记录X集合和Y集合在相等子图中的状态。
int line[maxn];//line[i]为Y集合中i与X集合中的line[i]配对
int we[maxn];//已配对所对应的边权值
int n,m,cnt,slack;
int head[maxn];
struct EDGE
{
int u,v,w,next;
}edge[maxm];
bool find(int u)
{
visx[u]=true;
for(int e=head[u];e!=-1;e=edge[e].next){
int v=edge[e].v;
if(!visy[v])
{
int t=lx[u]+ly[v]-edge[e].w;
if(t==0)
{
visy[v]=true;
if(line[v]==-1||find(line[v])){
line[v]=u;
we[v]=edge[e].w;//记录权值
return 1;
}
}
else if(t<slack){
slack=t;
}
}
}
return 0;
}
bool KM()
{
memset(ly,0,sizeof(ly));
memset(lx,0,sizeof(lx));
memset(line,-1,sizeof(line));
for(int u=1;u<=n;u++)
{
for(int e=head[u];e!=-1;e=edge[e].next)
{
if(edge[e].w>lx[u])
lx[u]=edge[e].w;
}
}
for(int u=1;u<=n;u++)
{
while(true)
{
slack=INF;
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
if(find(u))break;
if(slack==INF)return 0;
for(int i=1;i<=n;i++)
{
if(visx[i])lx[i]-=slack;
if(visy[i])ly[i]+=slack;
}
}
}
return 1;
}
void addedge(int u,int v,int w)
{
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;
}
struct KM{
double lx[N],ly[N];//顶标
bool visx[N],visy[N];
int line[N];
double we[N];//已配对所对应边权值
int nx,ny;
double slack;
bool find(int u){
visx[u]=true;
for(int v=1;v<=ny;v++){
if(!visy[v])//v不在相等子图中
{
double t=lx[u]+ly[v]-G[u][v];
if(fabs(t)<eps){
visy[v]=1;
if(line[v]==-1||find(line[v])){
line[v]=u;
ans[u]=v;
we[v]=G[u][v];
return 1;
}
}
}
}
return 0;
}
bool km(){//返回是否完备匹配
for(int i=1;i<=nx;i++){
lx[i]=-INF;ly[i]=0;
line[i]=-1;
for(int j=1;j<=ny;j++){
if(G[i][j]-lx[i]>eps)
lx[i]=G[i][j];//初始化为xi所连接的最大权值
}
}
for(int u=1;u<=nx;u++)
{
while(true){
clr(visx);clr(visy);
if(find(u))break;
for(int i=1;i<=nx;i++){
if(visx[i])lx[i]-=slack;
}
for(int i=1;i<=ny;i++){
if(visy[i])ly[i]+=slack;
}
slack=INF;
for(int i=1;i<=nx;i++){
if(visx[i]){
for(int j=1;j<=ny;j++){
if(!visy[j]){
slack=min(slack,lx[i]+ly[j]-G[i][j]);
}
}
}
}
if(slack==INF)break;
}
}
return 1;
}
int best_match(){
double res=0;
km();
for(int u=1;u<=ny;u++){
if(line[u]==-1)continue;
res+=we[u];
}
return res;
}
}kk;