题目很简单,就是要求一个二分图的二分匹配
数据范围不大,可以用KM算法,也可以用费用流
#include <bits/stdc++.h>
const int maxn = 105;
const int inf = 0x3f3f3f3f;
using namespace std;
typedef long long ll;
struct note{
int u, v, w, cost;
int next;
} e1[maxn * maxn * 2], e2[maxn * maxn * 2];
int head[maxn << 1], cnt; //两个图可以共用一个head[]数组,减少代码量
int n, s, t;
void add(int u, int v, int w, int c){
e1[cnt] = (note){u, v, w, c, head[u]};
e2[cnt] = (note){u, v, w, -c, head[u]};
head[u] = cnt++;
e1[cnt] = (note){v, u, 0, -c, head[v]};
e2[cnt] = (note){v, u, 0, c, head[v]};
head[v] = cnt++;
}
bool vis[maxn<<1];
int flow[maxn << 1], cost[maxn << 1], pre[maxn << 1], last[maxn << 1];
bool spfa(note e[]){
for (int i = s; i<=t; i++){
cost[i] = flow[i] = inf;
vis[i] = false;
}
cost[s] = 0;
pre[t] = -1;
queue<int> q;
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; ~i; i=e[i].next){
int v = e[i].v, w = e[i].w, c = e[i].cost;
if(w > 0 && cost[v] > cost[u] + c){
cost[v] = cost[u] + c;
pre[v] = u, last[v] = i;
flow[v] = min(flow[u], w);
if(!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
return pre[t] != -1;
}
int mincost;
int MCMF(note e[]){
while(spfa(e)){
mincost += flow[t] * cost[t];
int now = t;
while(now != s){
e[last[now]].w -= flow[t];
e[last[now] ^ 1].w += flow[t];
now = pre[now];
}
}
return mincost;
}
int main()
{
scanf("%d", &n);
memset(head, -1, sizeof(head));
s = 0, t = 2 * n + 1;
for (int i = 1; i <= n; i++){
add(s, i, 1, 0), add(i + n, t, 1, 0);
for (int j = 1; j <= n; j++){
int w;
scanf("%d", &w);
add(i, j + n, 1, w);
}
}
printf("%d
", MCMF(e1));
mincost = 0;
printf("%d
", -MCMF(e2));
return 0;
}