Desciption
Solution
一眼题,求费用流的最小割
然后实现用了两个晚上,我果然还是太弱了。。
这里需要说明的是,那些幸福度为0的情侣是不能连边的,不然会作为一条占用流量的无用边
然后这里的每个男孩只能爱一个女孩,那么也不能暴力枚举删哪条边了,
这是一个稠密图,那么只能上zkw过了
以上
Code
#include <stdio.h>
#include <string.h>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define min(x, y) (x)<(y)?(x):(y)
#define INF 0x3f3f3f3f
#define N 201
#define E N * N + 1
struct edge{int x, y, w, c, next;}e[E];
int lim[E], ls[N];
inline void addEdge(int &cnt, int x, int y, int w, int c){
cnt += 1; e[cnt] = (edge){x, y, w, c, ls[x]}; ls[x] = cnt; lim[cnt] = w;
cnt += 1; e[cnt] = (edge){y, x, 0, -c, ls[y]}; ls[y] = cnt; lim[cnt] = 0;
// printf("%d %d %d \n", x, y, c);
}
int vis[N], dis[N], nex[N];
int cost;
inline int find(int now, int ed, int mn){
if (now == ed || !mn){
return mn;
}
int ret = 0;
vis[now] = 1;
erg(i, now){
if (e[i].w > 0 && dis[e[i].y] + e[i].c == dis[now] && !vis[e[i].y]){
int d = find(e[i].y, ed, min(mn - ret, e[i].w));
if (d){
nex[e[i].x] = i;
}
cost += d * e[i].c;
e[i].w -= d;
e[i ^ 1].w += d;
ret += d;
if (ret == mn){
break;
}
}
}
return ret;
}
inline int modify(int st, int ed){
int mn = INF, inf = INF;
rep(now, st, ed){
if (vis[now]){
erg(i, now){
if (!vis[e[i].y] && e[i].w > 0){
mn = min(mn, dis[e[i].y] + e[i].c - dis[now]);
}
}
}
}
if (mn == inf){
return 0;
}
rep(i, st, ed){
if (vis[i]){
dis[i] += mn;
}
}
return 1;
}
inline void zkw(int st, int ed){
fill(dis, 0);
do{
rep(i, st, ed){
vis[i] = 0;
}
while (find(st, ed, INF)){
rep(i, st, ed){
vis[i] = 0;
}
}
} while (modify(st, ed));
}
int rec[N];
int main(void){
int n;
scanf("%d", &n);
int edgeCnt = 1;
int st = 0, ed = n * 2 + 1;
rep(i, 1, n){
rep(j, 1, n){
int tmp;
scanf("%d", &tmp);
if (tmp){
addEdge(edgeCnt, i, j + n, 1, -tmp);
}
}
addEdge(edgeCnt, st, i, 1, 0);
addEdge(edgeCnt, i + n, ed, 1, 0);
}
zkw(st, ed);
rep(i, 1, n){
rec[i] = nex[i];
}
int ans = cost;
printf("%d\n", -cost);
rep(i, 1, n){
rep(j, 2, edgeCnt){e[j].w = lim[j];}
e[rec[i]].w = e[rec[i] ^ 1].w = cost = 0;
zkw(st, ed);
if (ans < cost){
printf("%d %d\n", i, e[rec[i]].y - n);
}
}
return 0;
}c