KM-最小权完美匹配
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <utility>
using namespace std;
const int N =105;
const int M =10005;
const int inf =0x1fffffff;
int n, m, tot, lx[N], ly[N], match[N], h[N], v[M], w[M], nxt[M];
bool visx[N], visy[N];
int lack;
void add(int a, int b, int c)
{
v[tot] = b;
w[tot] = c;
nxt[tot] = h[a];
h[a] = tot++;
}
bool find(int u)
{
int i, t;
visx[u] =true;
for(i = h[u]; i !=-1; i = nxt[i])
if(!visy[v[i]])
{
t = w[i] - lx[u] - ly[v[i]];
if(t ==0)
{
visy[v[i]] =true;
if(match[v[i]]==-1|| find(match[v[i]]))
{
match[v[i]] = u;
return true;
}
}
else if(t >0)
lack = min(lack, t);
}
return false;
}
int calMatch(int n) {
int ans = 0;
for(int i =1; i <= n; i++)
{
lx[i] = inf;
ly[i] =0;
for(int j = h[i]; j !=-1; j = nxt[j])
lx[i] = min(lx[i], w[j]);
}
memset(match, -1, sizeof(match));
for(int i =1; i <= n; i++)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
lack = inf;
while(!find(i))
{
for(int j =1; j <= n; j++)
{
if(visx[j]) lx[j] += lack;
if(visy[j]) ly[j] -= lack;
}
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
}
}
ans = 0;
for(int i =1; i <= n; i++) ans = ans + lx[i] + ly[i];
return ans;
}
}}}
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <utility>
using namespace std;
const int N =105;
const int M =10005;
const int inf =0x1fffffff;
int n, m, tot, lx[N], ly[N], match[N], h[N], v[M], w[M], nxt[M];
bool visx[N], visy[N];
int lack;
void add(int a, int b, int c)
{
v[tot] = b;
w[tot] = c;
nxt[tot] = h[a];
h[a] = tot++;
}
bool find(int u)
{
int i, t;
visx[u] =true;
for(i = h[u]; i !=-1; i = nxt[i])
if(!visy[v[i]])
{
t = w[i] - lx[u] - ly[v[i]];
if(t ==0)
{
visy[v[i]] =true;
if(match[v[i]]==-1|| find(match[v[i]]))
{
match[v[i]] = u;
return true;
}
}
else if(t >0)
lack = min(lack, t);
}
return false;
}
int calMatch(int n) {
int ans = 0;
for(int i =1; i <= n; i++)
{
lx[i] = inf;
ly[i] =0;
for(int j = h[i]; j !=-1; j = nxt[j])
lx[i] = min(lx[i], w[j]);
}
memset(match, -1, sizeof(match));
for(int i =1; i <= n; i++)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
lack = inf;
while(!find(i))
{
for(int j =1; j <= n; j++)
{
if(visx[j]) lx[j] += lack;
if(visy[j]) ly[j] -= lack;
}
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
}
}
ans = 0;
for(int i =1; i <= n; i++) ans = ans + lx[i] + ly[i];
return ans;
}