思路:
构图:i 和 j 公用元素k[i][j],把数组A[i] , B[j]分别看成节点,那么A[i]可以流向B[j]大小最多为k[i][j],最少1的流量,但是网络流中最小流量为0,所以每行的和减去m,每列的和减去n,(每个元素减1).源点连A[i],容量为A[i],B[j]连汇点,容量为B[j],A[i] , B[j]连容量19的边。跑网络流,如果到汇点的和 == 矩阵的和,那么存在结果。将A[i] 到B[j]的流量加1输出即可
Code:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e3+6;
int A[AX];
int b[AX];
int m , n ;
struct Node{
int from , to , cap , flow;
Node( int u , int v , int c , int f ):from(u),to(v),cap(c),flow(f){}
};
std::vector<Node> edge;
std::vector<int> G[AX];
std::vector<int> vec;
int a[AX];
int p[AX];
int res[AX][AX];
void init(){
for( int i = 0 ; i < n ; i++ ) G[i].clear();
for( int i = 0 ; i < m ; i++ ) G[i+n].clear();
edge.clear();
}
int st = 100;
int ed = 101;
void addedge( int u ,int v ,int cap ){
edge.push_back( Node( u , v , cap , 0 ) );
edge.push_back( Node( v , u , 0 , 0 ) );
int size = edge.size();
if( u != st && v != ed ){
vec.push_back( size - 2 );
}
G[u].push_back(size-2);
G[v].push_back(size-1);
}
int Maxflow( int s , int t ){
int flow = 0;
while( true ){
memset( a, 0 , sizeof(a) );
queue<int>que;
que.push(s);
a[s] = INF;
while( !que.empty() ){
int x = que.front();
que.pop();
for( int i = 0 ; i < G[x].size() ; i++ ){
Node& e = edge[G[x][i]];
if( !a[e.to] && e.cap > e.flow ){
p[e.to] = G[x][i];
a[e.to] = min( a[x] , e.cap - e.flow );
que.push(e.to);
}
}
if( a[t] ) break;
}
if( !a[t] ) break;
for( int i = t ; i != s ; i = edge[p[i]].from ){
edge[p[i]].flow += a[t];
res[ edge[p[i]].from ][ i ] = edge[p[i]].flow;
edge[p[i]^1].flow -= a[t];
}
flow += a[t];
}
return flow;
}
int main(){
int sum = 0 ;
scanf("%d%d",&n,&m);
init();
for( int i = 0 ; i < n ; i++ ){
scanf("%d",&A[i]);
A[i] -= m;
addedge( st , i , A[i] );
}
for( int i = 0 ; i < m ; i++ ){
scanf("%d",&b[i]);
b[i] -= n ;
addedge( i + n , ed , b[i] );
sum += b[i];
}
for( int i = 0 ; i < n ; i ++ ){
for( int j = 0 ; j < m ; j ++ ){
addedge( i , j + n , 19 );
}
}
int ans = Maxflow( st , ed );
if( ans == sum ){
printf("Yes\n");
for( int i = 0 ; i < vec.size() ; i++ ){
if( i && i % m == 0 ){
printf("\n");
}
printf("%d ",edge[vec[i]].flow+1);
}
}else{
printf("No\n");
}
return 0 ;
}