传送门 思路:原来想用dfs做,然后果断wa Tle,后来才知道要用KM最大权值匹配,学习了。
AC代码:
using namespace std;
const int maxn = 400, INF = 0x7fffffff;
int usedx[maxn], usedy[maxn], w[maxn][maxn], bx[maxn], by[maxn], cx[maxn], cy[maxn];
int nx, ny, n, minn, max_value;
int dfs(int u)
{
usedx[u] = 1;
for(int i=1; i<=ny; i++)
{
if(usedy[i] == -1)
{
int t = bx[u] + by[i] - w[u][i];
if(t == 0)
{
usedy[i] = 1;
if(cy[i] == -1 || dfs(cy[i]))
{
cy[i] = u;
cx[u] = i;
return 1;
}
}
else if(t > 0)
minn = min(minn, t);
}
}
return 0;
}
int km()
{
mem(cx, -1);
mem(cy, -1);
mem(bx, -1);
mem(by, 0);
for(int i=1; i<=nx; i++)
for(int j=1; j<=ny; j++)
bx[i] = max(bx[i], w[i][j]);
for(int i=1; i<=nx; i++)
{
while(1)
{
minn = INF;
mem(usedx, -1);
mem(usedy, -1);
if(dfs(i)) break;
for(int j=1; j<=nx; j++)
if(usedx[j] != -1) bx[j] -= minn;
for(int j=1; j<=ny; j++)
if(usedy[j] != -1) by[j] += minn;
}
}
max_value = 0;
for(int i=1; i<=nx; i++)
if(cx[i] != -1)
max_value += w[i][cx[i]];
printf("%d\n",max_value);
return 1;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&w[i][j]);
nx = ny = n;
km();
}
return 0;
}