建图很简单,每行每列看成一个点。。原点到行点连一条流量为行值的边,列点到汇点连一条流量为列值的边。。每个行点到每个列点连一条流量为K的边。。。跑最大流,如果满流,则肯定有解。。。判断多解和唯一解很麻烦。。对于每个行点,在残余网络中dfs找能不能回到该点。。。如果能则多解,否则唯一解。。。注意dfs的时候每次走到下一点的时候不能立即走其反向边。。原理我觉得是判断行列之间的流量是否有影响,如果一点的流量能不通过其反向边流回该点,说明行列之间能通过流量调节达到平衡。。也就是说有多解。。
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 805
#define maxm 400005
#define eps 1e-10
#define mod 1000000009
#define INF 99999999
#define lowbit(x) (x&(-x))
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
//typedef int LL;
using namespace std;
int row[maxn], col[maxn];
struct Edge
{
int to, cap, flow, next;
};
struct dinic
{
int n, m, s, t, ok, uu;
Edge e[maxm];
int h[maxn];
queue<int> q;
bool vis[maxn];
int dis[maxn];
int cur[maxn];
void init(void)
{
m = 2;
memset(h, -1, sizeof h);
}
void add_edges(int from, int to, int cap)
{
e[m].next = h[from], e[m].to = to, h[from] = m, e[m].cap = cap, e[m].flow = 0, m++;
e[m].next = h[to], e[m].to = from, h[to] = m, e[m].cap = 0, e[m].flow = 0, m++;
}
bool BFS(void)
{
memset(vis, 0, sizeof vis);
q.push(s), dis[s] = 0, vis[s] = 1;
while(!q.empty()) {
int x = q.front(); q.pop();
for(int i = h[x]; ~i; i = e[i].next) {
if(!vis[e[i].to] && e[i].cap > e[i].flow) {
vis[e[i].to] = 1;
dis[e[i].to] = dis[x] + 1;
q.push(e[i].to);
}
}
}
return vis[t];
}
int DFS(int x, int a)
{
if(x == t || a == 0) return a;
int flow = 0, f;
int& i = cur[x];
if(i == 0) i = h[x];
for(; ~i; i = e[i].next) {
if(dis[x] + 1 == dis[e[i].to] && (f = DFS(e[i].to, min(a, e[i].cap - e[i].flow))) > 0) {
e[i].flow += f;
e[i^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int max_flow(void)
{
int flow = 0;
while(BFS()) {
memset(cur, 0, sizeof cur);
flow += DFS(s, INF);
}
return flow;
}
void dfs(int fa, int u)
{
if(vis[u]) return;
vis[u] = 1;
if(u == uu || !ok) {
ok = 0;
return;
}
for(int i = h[u]; ~i && ok; i = e[i].next) {
if(e[i].to == s || e[i].to == t) continue;
if(!(e[i].cap > e[i].flow)) continue;
if(e[i].to != fa) dfs(u, e[i].to);
}
}
bool check(void)
{
ok = 1;
for(int i = 1; i <= n && ok; i++) {
memset(vis, 0, sizeof vis);
uu = i;
for(int j = h[i]; ~j && ok; j = e[j].next) {
if(e[j].to == s || e[j].to == t) continue;
if(e[j].cap > e[j].flow) dfs(i, e[j].to);
}
}
if(!ok) printf("Not Unique\n");
else printf("Unique\n");
if(ok) return false;
else return true;
}
}tmp;
int n, m, k, tot;
int g[405][405];
void build(void)
{
tmp.n = n+m+2, tmp.s = 0, tmp.t = n+m+1;
tmp.init();
for(int i = 1; i <= n; i++) tmp.add_edges(tmp.s, i, row[i]);
for(int i = n+1; i <= n+m; i++) tmp.add_edges(i, tmp.t, col[i-n]);
for(int i = 1; i <= n; i++)
for(int j = n+1; j <= n+m; j++)
tmp.add_edges(i, j, k);
}
void work(void)
{
if(tot != tmp.max_flow()) {
printf("Impossible\n");
return;
}
for(int i = 1; i <= n; i++) {
int cnt = m;
for(int j = tmp.h[i]; ~tmp.e[j].next; j = tmp.e[j].next)
if(tmp.e[j].cap != 0)
g[i][cnt--] = tmp.e[j].flow;
}
tmp.n = n, tmp.m = m;
if(tmp.check()) return;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
printf("%d%c", g[i][j], j < m ? ' ' : '\n');
}
int main(void)
{
while(scanf("%d%d%d", &n, &m, &k)!=EOF) {
tot = 0;
for(int i = 1; i <= n; i++) scanf("%d", &row[i]), tot += row[i];
for(int i = 1; i <= m; i++) scanf("%d", &col[i]);
build();
work();
}
return 0;
}