int W[maxn][maxn],n;
int Lx[maxn],Ly[maxn];//顶标
int left[maxn];//left[i]为右边第i个点的编号
bool S[maxn],T[maxn]; //S[i]和T[i]为左或右第i个点是否已经被标记
bool match(int i)//寻找从i出发的对应项出的可增广路
{
S[i]=true;
for(int j=1;j<=n;j++)
{
if(Lx[i]+Ly[j]==W[i][j] && !T[j])//j不在增广路
{
T[j]=true;//把j加入增广路
if(!left[j] || match(left[j]))//j是未盖点或者从j的对应项出发有增广路
{
left[j]=i;//修改j的对应项为i
return true;
}
}
}
return false;//从k的对应项出发没有可增广路
}
void update()
{
int a=1<<30;
for(int i=1;i<=n;i++)
if(S[i])
for(int j=1;j<=n;j++)
if(!T[j])
{
a=min(a,Lx[i]+Ly[j]-W[i][j]);
}
for(int i=1;i<=n;i++)
{
if(S[i]) Lx[i]-=a;
if(T[i]) Ly[i]+=a;
}
}
void KM()//匈牙利
{
for(int i=1;i<=n;i++)//初始化
{
left[i]=Lx[i]=Ly[j]=0;
for(int j=1;j<=n;j++)
{
Lx[i]=max(Lx[i],W[i][j]);
}
}
/*
枚举S和T中的每一个元素
*/
for(int i=1;i<=n;i++)
{
for(;;)
{
for(int j=1;j<=n;j++)
{
S[j]=T[j]=0;
}
if(match(i)) break;//判断从i的对应项出有可增广路
else update();//加入结点
}
}
}
匈牙利算法(4次方级)
最新推荐文章于 2023-05-02 21:27:27 发布