题意
题解
二分答案+可行流判断。
模板题。
CODE
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
using namespace std;
template<class T>inline void read(T &x) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');x*=flg;
}
const int MAXN = 420;
const int MAXM = 50005;
const int inf = 1000000000;
int n, m, L, R, out[MAXN], in[MAXN];
int info[MAXN], fir[MAXN], to[MAXM<<1], nxt[MAXM<<1], c[MAXM<<1], cnt = 1;
inline void link(int u, int v, int cc, int rc=0) {
to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; c[cnt] = cc;
to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt; c[cnt] = rc;
}
int S, T, dis[MAXN];
queue<int>q; bool vis[MAXN];
bool bfs() {
memset(dis, -1, sizeof dis);
dis[S] = 0; q.push(S);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = fir[u]; i; i = nxt[i])
if(c[i] && !~dis[to[i]])
dis[to[i]] = dis[u] + 1, q.push(to[i]);
}
return ~dis[T];
}
int aug(int u, int Max) {
if(u == T) return Max;
vis[u] = 1; int flow = 0, delta;
for(int v, &i = info[u]; i; i = nxt[i])
if(c[i] && !vis[v=to[i]] && dis[v] == dis[u] + 1 && (delta=aug(v, min(Max-flow, c[i])))) {
c[i] -= delta, c[i^1] += delta, flow += delta;
if(flow == Max) break;
}
vis[u] = 0; return flow;
}
int Maxflow(int s, int t) {
int re = 0; S = s, T = t;
while(bfs()) memcpy(info, fir, sizeof info), re += aug(S, inf);
return re;
}
int rs[205], cs[205];
int rid[205], cid[205];
inline void add(int u, int v, int ll, int rr) {
link(u, v, rr-ll);
in[v] += ll;
out[u] += ll;
}
inline bool chk(int mid) {
memset(in, 0, sizeof in);
memset(out, 0, sizeof out);
memset(fir, 0, sizeof fir); cnt = 1;
int tot = 0, s = ++tot, t = ++tot;
for(int i = 1; i <= n; ++i) rid[i] = ++tot, add(s, rid[i], max(rs[i]-mid, 0), rs[i]+mid);
for(int i = 1; i <= m; ++i) cid[i] = ++tot, add(cid[i], t, max(cs[i]-mid, 0), cs[i]+mid);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) add(rid[i], cid[j], L, R);
int ss = ++tot, tt = ++tot, sum = 0;
for(int i = 1; i < ss; ++i) {
if(in[i]>out[i]) link(ss, i, in[i]-out[i]), sum += in[i]-out[i];
if(in[i]<out[i]) link(i, tt, out[i]-in[i]);
}
link(t, s, inf, 0);
sum -= Maxflow(ss, tt);
return !sum;
}
int main () {
read(n), read(m);
for(int i = 1; i <= n; ++i)
for(int j = 1, x; j <= m; ++j)
read(x), rs[i] += x, cs[j] += x;
read(L), read(R);
int l = 0, r = 1000*max(n,m), mid;
while(l < r) {
mid = (l + r) >> 1;
if(chk(mid)) r = mid;
else l = mid+1;
}
printf("%d
", l);
}