This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://atcoder.jp/contests/abc259/tasks/abc259_g"
#include "template.hpp"
#include "flow/binary-optimization.hpp"
int main(){
cin.tie(nullptr)->sync_with_stdio(false);
int n,m;
cin >> n >> m;
vector a(n,vector<ll>(m));
vector<ll> sumh(n),sumv(m);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin >> a[i][j];
sumh[i]+=a[i][j];
sumv[j]+=a[i][j];
}
}
BinaryOptimization<ll,false> b(n+m);
for(int i=0;i<n;i++)b.add1(i,sumh[i],0);
for(int i=0;i<m;i++)b.add1(i+n,0,sumv[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(a[i][j]<0){
b.add2(i,j+n,0,-LINF,0,0);
}else{
b.add2(i,j+n,0,-a[i][j],0,0);
}
}
}
cout << b.solve();
}
#line 1 "verify/atcoder/abc259_g.cpp"
#define PROBLEM "https://atcoder.jp/contests/abc259/tasks/abc259_g"
#line 1 "template.hpp"
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using db = long double;
using vi = vector<int>;
using vl = vector<ll>;
using vd = vector<db>;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pdd = pair<db,db>;
const int INF=INT_MAX/2;
const int MOD=998244353;
const int MOD2=1000000007;
const ll LINF=LLONG_MAX/2;
const db DINF=numeric_limits<db>::infinity();
const db EPS=1e-9;
const db PI=acos(db(-1));
template<class T>
using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
template<class T>
using ordered_multiset = tree<T,null_type,less_equal<T>,rb_tree_tag,tree_order_statistics_node_update>;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rng64(chrono::steady_clock::now().time_since_epoch().count());
#line 2 "flow/dinic.hpp"
/**
* Author: Teetat T.
* Date: 2024-07-15
* Description: Dinic's Algorithm for finding the maximum flow.
* Time: O(V E \log U) where U is the maximum flow.
*/
template<class T,bool directed=true,bool scaling=true>
struct Dinic{
static constexpr T INF=numeric_limits<T>::max()/2;
struct Edge{
int to;
T flow,cap;
Edge(int _to,T _cap):to(_to),flow(0),cap(_cap){}
T remain(){return cap-flow;}
};
int n,s,t;
T U;
vector<Edge> e;
vector<vector<int>> g;
vector<int> ptr,lv;
bool calculated;
T max_flow;
Dinic(){}
Dinic(int n,int s,int t){init(n,s,t);}
void init(int _n,int _s,int _t){
n=_n,s=_s,t=_t;
U=0;
e.clear();
g.assign(n,{});
calculated=false;
}
void add_edge(int from,int to,T cap){
assert(0<=from&&from<n&&0<=to&&to<n);
g[from].emplace_back(e.size());
e.emplace_back(to,cap);
g[to].emplace_back(e.size());
e.emplace_back(from,directed?0:cap);
U=max(U,cap);
}
bool bfs(T scale){
lv.assign(n,-1);
vector<int> q{s};
lv[s]=0;
for(int i=0;i<(int)q.size();i++){
int u=q[i];
for(int j:g[u]){
int v=e[j].to;
if(lv[v]==-1&&e[j].remain()>=scale){
q.emplace_back(v);
lv[v]=lv[u]+1;
}
}
}
return lv[t]!=-1;
}
T dfs(int u,int t,T f){
if(u==t||f==0)return f;
for(int &i=ptr[u];i<(int)g[u].size();i++){
int j=g[u][i];
int v=e[j].to;
if(lv[v]==lv[u]+1){
T res=dfs(v,t,min(f,e[j].remain()));
if(res>0){
e[j].flow+=res;
e[j^1].flow-=res;
return res;
}
}
}
return 0;
}
T flow(){
if(calculated)return max_flow;
calculated=true;
max_flow=0;
for(T scale=scaling?1LL<<(63-__builtin_clzll(U)):1LL;scale>0;scale>>=1){
while(bfs(scale)){
ptr.assign(n,0);
while(true){
T f=dfs(s,t,INF);
if(f==0)break;
max_flow+=f;
}
}
}
return max_flow;
}
pair<T,vector<int>> cut(){
flow();
vector<int> res(n);
for(int i=0;i<n;i++)res[i]=(lv[i]==-1);
return {max_flow,res};
}
};
#line 3 "flow/binary-optimization.hpp"
/**
* Author: Teetat T.
* Date: 2024-07-1ุ6
* Description: Binary Optimization.
* minimize $\kappa + \sum_i \theta_i(x_i) + \sum_{i<j} \phi_{ij}(x_i,x_j) + \sum_{i<j<k} \psi_{ijk}(x_i,x_j,x_k)$
* where $x_i \in \{0,1\}$ and $\phi_{ij},\psi_{ijk}$ are submodular functions.
* a set function $f$ is submodular if $f(S) + f(T) \geq f(S \cap T) + f(S \cup T)$ for all $S,T$.
* $\phi_{ij}(0,1) + \phi_{ij}(1,0) \geq \phi_{ij}(1,1) + \phi_{ij}(0,0)$.
*/
template<class T,bool minimize=true>
struct BinaryOptimization{
static constexpr T INF=numeric_limits<T>::max()/2;
int n,s,t,node_id;
T base;
map<pair<int,int>,T> edges;
BinaryOptimization(int _n):n(_n),s(n),t(n+1),node_id(n+2),base(0){}
void add_edge(int u,int v,T w){
assert(w>=0);
if(u==v||w==0)return;
auto &e=edges[{u,v}];
e=min(e+w,INF);
}
void add0(T w){
base+=w;
}
void _add1(int i,T a,T b){
if(a<=b){
add0(a);
add_edge(s,i,b-a);
}else{
add0(b);
add_edge(i,t,a-b);
}
}
void add1(int i,T x0,T x1){
assert(0<=i&&i<n);
if(!minimize)x0=-x0,x1=-x1;
_add1(i,x0,x1);
}
void _add2(int i,int j,T a,T b,T c,T d){
assert(b+c>=a+d);
add0(a);
_add1(i,0,c-a);
_add1(j,0,d-c);
add_edge(i,j,b+c-a-d);
}
void add2(int i,int j,T x00,T x01,T x10,T x11){
assert(i!=j&&0<=i&&i<n&&0<=j&&j<n);
if(!minimize)x00=-x00,x01=-x01,x10=-x10,x11=-x11;
_add2(i,j,x00,x01,x10,x11);
}
void _add3(int i,int j,int k,T a,T b,T c,T d,T e,T f,T g,T h){
T p=a+d+f+g-b-c-e-h;
if(p>=0){
add0(a);
_add1(i,0,f-b);
_add1(j,0,g-e);
_add1(k,0,d-c);
_add2(i,j,0,c+e-a-g,0,0);
_add2(i,k,0,0,b+e-a-f,0);
_add2(j,k,0,b+c-a-d,0,0);
int u=node_id++;
add0(-p);
add_edge(i,u,p);
add_edge(j,u,p);
add_edge(k,u,p);
add_edge(u,t,p);
}else{
add0(h);
_add1(i,c-g,0);
_add1(j,b-d,0);
_add1(k,e-f,0);
_add2(i,j,0,0,d+f-b-h,0);
_add2(i,k,0,d+g-c-h,0,0);
_add2(j,k,0,0,f+g-e-h,0);
int u=node_id++;
add0(p);
add_edge(s,u,-p);
add_edge(u,i,-p);
add_edge(u,j,-p);
add_edge(u,k,-p);
}
}
void add3(int i,int j,int k,T x000,T x001,T x010,T x011,T x100,T x101,T x110,T x111){
assert(i!=j&&j!=k&&k!=i&&0<=i&&i<n&&0<=j&&j<n&&0<=k&&k<n);
if(!minimize){
x000=-x000,x001=-x001,x010=-x010,x011=-x011;
x100=-x100,x101=-x101,x110=-x110,x111=-x111;
}
_add3(i,j,k,x000,x001,x010,x011,x100,x101,x110,x111);
}
T solve(){
Dinic<T> dinic(node_id,s,t);
for(auto &[p,w]:edges){
auto [u,v]=p;
dinic.add_edge(u,v,w);
}
T ans=dinic.flow()+base;
return minimize?ans:-ans;
}
};
#line 4 "verify/atcoder/abc259_g.cpp"
int main(){
cin.tie(nullptr)->sync_with_stdio(false);
int n,m;
cin >> n >> m;
vector a(n,vector<ll>(m));
vector<ll> sumh(n),sumv(m);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin >> a[i][j];
sumh[i]+=a[i][j];
sumv[j]+=a[i][j];
}
}
BinaryOptimization<ll,false> b(n+m);
for(int i=0;i<n;i++)b.add1(i,sumh[i],0);
for(int i=0;i<m;i++)b.add1(i+n,0,sumv[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(a[i][j]<0){
b.add2(i,j+n,0,-LINF,0,0);
}else{
b.add2(i,j+n,0,-a[i][j],0,0);
}
}
}
cout << b.solve();
}