Problem Description
Alice and Bob are playing together. Alice is crazy about art and she has visited many museums around the world. She has a good memory and she can remember all drawings she has seen.

Today Alice designs a game using these drawings in her memory. First, she matches K+1 colors appears in the picture to K+1 different integers(from 0 to K). After that, she slices the drawing into grids and there are N rows and M columns. Each grid has an integer on it(from 0 to K) representing the color on the corresponding position in the original drawing. Alice wants to share the wonderful drawings with Bob and she tells Bob the size of the drawing, the number of different colors, and the sum of integers on each row and each column. Bob has to redraw the drawing with Alice's information. Unfortunately, somtimes, the information Alice offers is wrong because of Alice's poor math. And sometimes, Bob can work out multiple different drawings using the information Alice provides. Bob gets confused and he needs your help. You have to tell Bob if Alice's information is right and if her information is right you should also tell Bob whether he can get a unique drawing.

 
Input
The input contains mutiple testcases.

For each testcase, the first line contains three integers N(1 ≤ N ≤ 400) , M(1 ≤ M ≤ 400) and K(1 ≤ K ≤ 40).
N integers are given in the second line representing the sum of N rows.
M integers are given in the third line representing the sum of M columns.

The input is terminated by EOF.

 
Output
For each testcase, if there is no solution for Bob, output "Impossible" in one line(without the quotation mark); if there is only one solution for Bob, output "Unique" in one line(without the quotation mark) and output an N * M matrix in the following N lines representing Bob's unique solution; if there are many ways for Bob to redraw the drawing, output "Not Unique" in one line(without the quotation mark).
 
题目大意:有一个矩阵,矩阵的数为0~K。给出矩阵每一行每一列的和。若不存在符合条件的矩阵,输出Impossible。若存在但矩阵不唯一,输出Not Unique。否则输出Unique并输出这个矩阵。
思路:网络最大流,另外开一个源点S和汇点T,源点到每行连一条边,容量为每一行的和。每一列到汇点连一条边,容量为每一列的和。每一行到每一列连一条边,容量为K。判断每行的总和和每列的总和是否相等,不等则输出Impossible,若相等,令这个值为sum。若sum不等于最大流,输出Impossible。否则,判断网络流是否唯一,不唯一输出Not Unique,存在则输出Unique,输出矩阵,矩阵mat[i][j]的值对应第 i 行到第 j 列的边的流量。
至于判断网络流是否唯一,可以采取在残量网络中找环的办法(环的大小必须大于2),若存在环,那么环上的边全部加一,得到一个新的残量网络,则最大流网络不唯一。那么问题转换为如何找环,由于环必然有至少一个点在列点上,而残量网络中,汇点对所有的列点都有边,那么可以从汇点开始DFS找环。
DFS判是否存在环可以借鉴tarjan求双连通分量的算法,具体可以看代码(这一步的复杂度为O(V + E)即O(n^2),虽然更粗暴的方法也可以过,但是跑得没那么快。)。
 
代码(218MS):
 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <numeric>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXV = MAXN << ;
const int MAXE = * MAXN * MAXN;
const int INF = 0x3f3f3f3f; struct ISAP {
int head[MAXV], cur[MAXV], gap[MAXV], dis[MAXV], pre[MAXV];
int to[MAXE], next[MAXE], flow[MAXE];
int n, ecnt, st, ed; void init(int n) {
this->n = n;
memset(head + , -, n * sizeof(int));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} void bfs() {
memset(dis + , 0x3f, n * sizeof(int));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
gap[dis[u]]++;
for(int p = head[u]; ~p; p = next[p]) {
int v = to[p];
if(flow[p ^ ] && dis[u] + < dis[v]) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int max_flow(int ss, int tt) {
st = ss, ed = tt;
int ans = , minFlow = INF;
for(int i = ; i <= n; ++i) {
cur[i] = head[i];
gap[i] = ;
}
bfs();
int u = pre[st] = st;
while(dis[st] < n) {
bool flag = false;
for(int &p = cur[u]; ~p; p = next[p]) {
int v = to[p];
if(flow[p] && dis[u] == dis[v] + ) {
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed) {
ans += minFlow;
while(u != st) {
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if(flag) continue;
int minDis = n - ;
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(flow[p] && dis[v] < minDis) {
minDis = dis[v];
cur[u] = p;
}
}
if(--gap[dis[u]] == ) break;
++gap[dis[u] = minDis + ];
u = pre[u];
}
return ans;
} int stk[MAXV], top;
bool sccno[MAXV], vis[MAXV]; bool dfs(int u, int f, bool flag) {
vis[u] = true;
stk[top++] = u;
for(int p = head[u]; ~p; p = next[p]) if(flow[p]) {
int v = to[p];
if(v == f) continue;
if(!vis[v]) {
if(dfs(v, u, flow[p ^ ])) return true;
} else if(!sccno[v]) return true;
}
if(!flag) {
while(true) {
int x = stk[--top];
sccno[x] = true;
if(x == u) break;
}
}
return false;
} bool acycle() {
memset(sccno + , , n * sizeof(bool));
memset(vis + , , n * sizeof(bool));
top = ;
return dfs(ed, , );
}
} G; int row[MAXN], col[MAXN];
int mat[MAXN][MAXN];
int n, m, k, ss, tt; void solve() {
int sumr = accumulate(row + , row + n + , );
int sumc = accumulate(col + , col + m + , );
if(sumr != sumc) {
puts("Impossible");
return ;
}
int res = G.max_flow(ss, tt);
if(res != sumc) {
puts("Impossible");
return ;
}
if(G.acycle()) {
puts("Not Unique");
} else {
puts("Unique");
for(int i = ; i <= n; ++i) {
for(int j = ; j < m; ++j) printf("%d ", G.flow[mat[i][j]]);
printf("%d\n", G.flow[mat[i][m]]);
}
}
} int main() {
while(scanf("%d%d%d", &n, &m, &k) != EOF) {
for(int i = ; i <= n; ++i) scanf("%d", &row[i]);
for(int i = ; i <= m; ++i) scanf("%d", &col[i]);
ss = n + m + , tt = n + m + ;
G.init(tt);
for(int i = ; i <= n; ++i) G.add_edge(ss, i, row[i]);
for(int i = ; i <= m; ++i) G.add_edge(n + i, tt, col[i]);
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
mat[i][j] = G.ecnt ^ ;
G.add_edge(i, n + j, k);
}
}
solve();
}
}

HDU 4888 Redraw Beautiful Drawings(最大流+判最大流网络是否唯一)的更多相关文章

  1. hdu 4888 Redraw Beautiful Drawings(最大流,判环)

    pid=4888">http://acm.hdu.edu.cn/showproblem.php?pid=4888 加入一个源点与汇点,建图例如以下: 1. 源点 -> 每一行相应 ...

  2. hdu 4888 Redraw Beautiful Drawings 最大流

    好难好难,将行列当成X和Y,源汇点连接各自的X,Y集,容量为行列的和,相当于从源点流向每一行,然后分配流量给每一列,最后流入汇点,这样执意要推断最后是否满流,就知道有没有解,而解就是每一行流向每一列多 ...

  3. hdu 4888 Redraw Beautiful Drawings 网络流

    题目链接 一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图. 首先对行列建边, 源点向行 ...

  4. HDU 4888 Redraw Beautiful Drawings

    网络流. $s$向每一个$r[i]$连边,容量为$r[i]$. 每一个$r[i]$向每一个$c[j]$连边,容量为$k$. 每一个$c[j]$向$t$连边容量为$c[j]$. 跑最大流,中间每一条边上 ...

  5. HDU 4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

    题意:给定n*m个格子,每个格子能填0-k 的整数.然后给出每列之和和每行之和,问有没有解,有的话是不是唯一解,是唯一解输出方案. 思路:网络流,一共 n+m+2个点   源点 到行连流量为 所给的 ...

  6. HDU 4888 Redraw Beautiful Drawings 网络流 建图

    题意: 给定n, m, k 以下n个整数 a[n] 以下m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵.若有多解输出Not Unique,若无解输出Impossib ...

  7. 【HDU】4888 Redraw Beautiful Drawings 网络流【推断解是否唯一】

    传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因 ...

  8. hdu4888 Redraw Beautiful Drawings 最大流+判环

    hdu4888 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/6553 ...

  9. HDU Redraw Beautiful Drawings 推断最大流是否唯一解

    点击打开链接 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 ...

随机推荐

  1. Java程序员从笨鸟到菜鸟之(二十一)java过滤器和监听器详解 【转】

     过滤器 1.Filter工作原理(执行流程) 当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请 ...

  2. BLE-NRF51822教程16-BLE地址

    本教程基于 sdk9+sd8.0 51822的 BLE的设备地址 可以通过如下函数函数来获得 地址的设置可以调用如下函数设置. 官方的demo工程中,都是没有主动调用过 sd_ble_gap_addr ...

  3. OC文件大小的计算方法,多用于清理缓存

    OC文件大小的计算方法,一般多用于清理缓存.下载.统计 可以使用以下方法: #pragma mark Bt转换 + (NSString *)axcFileSizeWithToString:(unsig ...

  4. centos 重启php-fpm

    centos 重启php-fpm ps -ef | grep php-fpm 查看php-fpm的配置文件,然后从配置文件查看php-fpm的pid文件,然后,  kill -SIGUSR2 `cat ...

  5. 【C】漫谈C语言随机数

    来说说C语言如何产生随机数. 有人会说这不简单?time() + srand() + rand() 3个函数不就OK了吗? 是的,不过,我们还是来看看原理比较好,也就是随机数是如何产生的. 这不无聊. ...

  6. ThreadPoolExecutor 分析

    一.从用法入手 Creates a thread pool that creates new threads as needed, but will reuse previously construc ...

  7. .NET对象与Windows句柄(三):句柄泄露实例分析

    在上篇文章.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子中,我们有一个句柄泄露的例子.例子中多次创建和Dispose了DataReceiver和DataAnalyzer对象, ...

  8. 有关sass

    一.sass编译为css文件 编译的方法有很多 1.koala编译  请参考 http://www.w3cplus.com/blog/777.html http://koala-app.com/ind ...

  9. [LeetCode]题解(python):052-N-Queens II

    题目来源 https://leetcode.com/problems/n-queens-ii/ Follow up for N-Queens problem. Now, instead outputt ...

  10. Fiddler-007-修改HTTP请求响应数据

    前文简述了如何通过 Fiddler 修改 HTTP请求 的请求参数,详情请参阅:Fiddler-006-修改HTTP请求参数. 在进行 App 测试时,经常需要修改请求参数,以获得不同的显示效果,以查 ...