km는 일부 카드 비용 흐름 문제를 해결할 수 있습니다.
시간 복잡성 n3
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstdlib>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int maxn = 350;
void acc_ios()
{
ios::sync_with_stdio(false);
cin.tie(0);
}
int mp[maxn][maxn];
int slack[maxn];
int nx, ny;
int lx[maxn], ly[maxn];
int visx[maxn], visy[maxn];
int link[maxn];
bool dfs(int x)
{
visx[x] = 1;
for(int i = 1; i <= ny; i++)
{
if(visy[i]) continue;
int tmp = lx[x] + ly[i] - mp[x][i];
if(tmp == 0)
{
visy[i] = 1;
if(link[i] == -1 || dfs(link[i]))
{
link[i] = x;
return true;
}
}
else if(slack[i] > tmp)
{
slack[i] = tmp;
}
}
return false;
}
int KM()
{
memset(link, -1, sizeof(link));
memset(ly, 0, sizeof(ly));
// memset(lx, -0x3f, sizeof(lx));
for(int i = 1; i <= nx; i++)
{
lx[i] = -inf;
for(int j = 1; j <= ny; j++)
{
lx[i] = max(mp[i][j], lx[i]);
}
}
for(int i = 1; i <= nx; i++)
{
for(int j = 1; j <= ny; j++)
slack[j] = inf;
while(1)
{
memset(visx, 0, sizeof(visx));
memset(visy, 0, sizeof(visy));
if(dfs(i)) break;
int d = inf;
for(int j = 1; j <= ny; j++)
if(!visy[j] && d > slack[j])
d = slack[j];
for(int j = 1; j <= nx; j++)
if(visx[j])
lx[j] -= d;
for(int j = 1; j <= ny; j++)
{
if(visy[j]) ly[j] += d;
else slack[j] -= d;
}
}
}
int ans = 0;
for(int i = 1; i <= ny; i++)
{
if(link[i] > -1)
ans += mp[link[i]][i];
}
return ans;
}
int main()
{
acc_ios();
int n;
while(cin>>n)
{
nx = ny = n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
cin>>mp[i][j];
}
}
cout<<KM()<<endl;
}
return 0;
}