您的位置:首页 > 其它

【KM算法】HDU2255-奔小康赚大钱

2016-04-04 15:59 429 查看
KM算法的裸体。O(n^4)的模板,实际上在增广路径的时候依然有冗余,可以用bfs优化到O(n^3)。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN=400+5;
const int INF=0x7fffffff;
int n,m;
int w[MAXN][MAXN];
int x[MAXN],y[MAXN];
int visx[MAXN],visy[MAXN],slack[MAXN];
int lk[MAXN];

int dfs(int u)
{
visx[u]=1;
for (int i=1;i<=n;i++)
{
int wt=x[u]+y[i]-w[u][i];
if (!visy[i] && wt==0)
{
visy[i]=1;
if (lk[i]==-1 || dfs(lk[i]))
{
lk[i]=u;
return 1;
}
}
else if (slack[i]>wt) slack[i]=wt;
}
return 0;
}

int KM()
{
memset(lk,-1,sizeof(lk));
for (int i=1;i<=n;i++)
{
y[i]=0;
x[i]=-INF;
for (int j=1;j<=n;j++) x[i]=max(x[i],w[i][j]);
}
for (int i=1;i<=n;i++)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
memset(slack,127,sizeof(slack));
while (!dfs(i))
{
int delta=INF;
for (int j=1;j<=n;j++)
if (!visy[j] && slack[j]<delta) delta=slack[j];
for (int j=1;j<=n;j++)
{
if (visx[j])
{
x[j]-=delta;
visx[j]=0;
}
if (visy[j])
{
y[j]+=delta;
visy[j]=0;
}
}
}
}
int ret=0;
for (int i=1;i<=n;i++) ret+=x[i]+y[i];
return ret;
}

void init()
{
memset(w,0,sizeof(w));
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
scanf("%d",&w[i][j]);
}
}

int main()
{
while (~scanf("%d",&n))
{
init();
printf("%d\n",KM());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: