E. Matrix Problem
time limit per test 1 second
memory limit per test 256 megabytes
inputstandard input
outputstandard output
You are given a matrix a, consisting of n n n rows by m m m columns. Each element of the matrix is equal to 0 0 0 or 1 1 1.
You can perform the following operation any number of times (possibly zero): choose an element of the matrix and replace it with either 0 0 0 or 1 1 1.
You are also given two arrays A A A and B B B (of length n n n and m m m respectively). After you perform the operations, the matrix should satisfy the following conditions:
Calculate the minimum number of operations you have to perform.
Input
The first line contains two integers n n n and m m m ( 2 ≤ n , m ≤ 50 ) (2\le n,m\le50) (2≤n,m≤50).
Then n n n lines follow. The i i i-th of them contains m m m integers a i , 1 , a i , 2 , … , a i , m ( 0 ≤ a i , j ≤ 1 ) a_{i,1},a_{i,2},…,a_{i,m}\ (0\le a_{i,j}\le1) ai,1,ai,2,…,ai,m (0≤ai,j≤1).
The next line contains n n n integers A 1 , A 2 , … , A n ( 0 ≤ A i ≤ m ) A_1,A_2,…,A_n\ (0\le A_i\le m) A1,A2,…,An (0≤Ai≤m).
The next line contains m m m integers B 1 , B 2 , … , B m ( 0 ≤ B i ≤ n ) B_1,B_2,…,B_m\ (0\le B_i\le n) B1,B2,…,Bm (0≤Bi≤n).
Output
Print one integer — the minimum number of operations you have to perform, or − 1 -1 −1 if it is impossible.
Examples
input
3 3
0 0 0
0 0 0
0 0 0
1 1 1
1 1 1
output
3
input
3 3
1 1 1
1 1 1
1 1 1
3 2 1
1 2 3
output
3
input
2 2
0 0
0 0
1 2
0 1
output
-1
思路:最小费用最大流。从源点 S S S建一条至 i i i的容量为 A i A_i Ai费用为0的有向边,从 j j j建一条至汇点 T T T的容量为 B j B_j Bj费用为0的有向边。同时 i , j i,j i,j之间建一条 i i i至 j j j且容量为1费用为 a i , j ⨁ 1 a_{i,j}\bigoplus 1 ai,j⨁1的有向边。
求出最小费用最大流 c , f c,f c,f后,若答案存在则有 f = ∑ A i = ∑ B j f=\sum A_i = \sum B_j f=∑Ai=∑Bj,其中有 c c c次操作将 a i , j = 0 a_{i,j}=0 ai,j=0变为 a i , j = 1 a_{i,j}=1 ai,j=1,那么在原图中有 f − c f-c f−c个 a i , j = 1 a_{i,j}=1 ai,j=1未发生变化,那么原图中多出来的 ∑ a i , j − ( f − c ) \sum a_{i,j}-(f-c) ∑ai,j−(f−c)个 1 1 1就需要变为 0 0 0。
所以最终操作次数为 c + ∑ a i , j − ( f − c ) = ∑ a i , j − f + 2 × c c+\sum a_{i,j}-(f-c)=\sum a_{i,j}-f+2\times c c+∑ai,j−(f−c)=∑ai,j−f+2×c。
#include
#define fi first
#define se second
#define lson (k<<1)
#define rson (k<<1)+1
#define mid ((l+r)/2)
#define sz(x) int(x.size())
#define pii pair<ll,ll>
#define bit bitset<100000>
using namespace std;
const int MAX=2e6+10;
const int MOD=1e9+7;
const int INF=INT_MAX/2;
const double PI=acos(-1.0);
typedef long long ll;
struct edg{int from,to,cap,cost,rev;};
class MCMF
{
struct node
{
int x,dis,flow;
bool operator<(const node& q) const {return q.dis<dis;}
};
private:
int s,t;
vector<int>h,d,v;
vector<edg*>p;
vector<vector<edg>>g;
private:
void Spfa() { //worst O(n*m)
fill(h.begin(),h.end(),INF);
fill(v.begin(),v.end(),0);
queue<int>q;
q.push(s);
h[s]=0;
while(!q.empty())
{
int x=q.front();q.pop();
v[x]=0;
for(auto &e:g[x])
{
int y=e.to;
if(!e.cap||h[y]<=h[x]+e.cost)continue;
h[y]=h[x]+e.cost;
if(v[y])continue;
v[y]=1;
q.push(y);
}
}
}
int Dijkstra(int flow) //O(m*log(n))
{
fill(v.begin(),v.end(),0);
fill(d.begin(),d.end(),-1);
fill(p.begin(),p.end(),nullptr);
priority_queue<node> q;
q.push({s,0,flow});
d[s]=0;
int ret=0;
while(!q.empty())
{
auto cur=q.top();q.pop();
int x=cur.x;
if(d[x]!=cur.dis)continue;
if(x==t)ret=cur.flow;
for(auto &e:g[x])
{
int y=e.to;
if(e.cap<=0)continue;
if(d[y]!=-1&&d[y]<=d[x]+e.cost+h[x]-h[y])continue;
d[y]=d[x]+e.cost+h[x]-h[y];
p[y]=&e;
q.push({y,d[y],min(cur.flow,e.cap)});
}
}
return ret;
}
public:
explicit MCMF(int _n,int _s,int _t)
{
s=_s,t=_t;
h.resize(_n);d.resize(_n);
v.resize(_n);p.resize(_n);g.resize(_n);
}
void AddEdg(int from,int to,int cap,int cost) {
g[from].push_back((edg){from,to,cap,cost,sz(g[to])});
g[to].push_back((edg){to,from,0,-cost,sz(g[from])-1});
}
pii MinCostMaxFlow(int flow)
{
// Spfa();
fill(h.begin(),h.end(),0);
int mf=0,mc=0,f=0;
while(f=Dijkstra(flow))
{
for(int i=0;i<sz(v);i++)h[i]+=d[i]; //update h
for(int i=t;p[i];i=p[i]->from) //update cap
{
p[i]->cap-=f;
g[p[i]->to][p[i]->rev].cap+=f;
}
flow-=f;
mf+=f;
mc+=f*h[t];
}
return {mf,mc};
}
};
int solve()
{
int n,m,s=0,sa=0,sb=0;
cin>>n>>m;
MCMF t(n+m+2,0,n+m+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int x;
scanf("%d",&x);
t.AddEdg(i,j+n,1,x^1);
s+=x;
}
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
sa+=x;
t.AddEdg(0,i,x,0);
}
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
sb+=x;
t.AddEdg(i+n,n+m+1,x,0);
}
int flow,cost;
tie(flow,cost)=t.MinCostMaxFlow(n*m);
if(flow!=sa||flow!=sb)return puts("-1");
return printf("%d\n",s-flow+2*cost);
}
int main()
{
int T=1;
//cin>>T;
while(T--)solve();
return 0;
}