建图很简单,每行每列看成一个点。。原点到行点连一条流量为行值的边,列点到汇点连一条流量为列值的边。。每个行点到每个列点连一条流量为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; }