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 JDK8 学习笔记——第18章 自定义泛型、枚举与注释

    第十八章 自定义泛型.枚举与注释 18.1 自定义泛型 泛型定义: (1)仅定义在方法上的泛型语法 (2)用来限制泛型可用类型的extends与super关键字(3)?类型通配字符的使用 18.1.1 ...

  2. ActiveMQ持久化消息

    ActiveMQ的另一个问题就是只要是软件就有可能挂掉,挂掉不可怕,怕的是挂掉之后把信息给丢了,所以本节分析一下几种持久化方式: 一.持久化为文件 ActiveMQ默认就支持这种方式,只要在发消息时设 ...

  3. CentOS联网

    虚拟机那里选择NAT模式 用vi /etc/sysconfig/network-scripts/ifcfg-eth0进到网卡文件修改ONBOOT=yes.意思是启动网卡 (注意在vi里,需要编辑时要按 ...

  4. css3 loading效果

    file:///E:/zhangqiangWork/2014/SPDbank/index.html 参考该网站 http://tobiasahlin.com/spinkit/ 查看源代码把里面的dom ...

  5. Internal Server Error500

    开启#LoadModule rewrite_module modules/mod_rewrite.so

  6. 经典Bug 修改方法

    右击工程名,“显示包内容”,删除提示错误的所有相关内容,(想当初,仅仅是删了一个图片,就各种报错,clean也没用,删了重新运行,也不成功.....有能力的话,最好能FQ,google你会发现很多技巧 ...

  7. HTML5中表单的创建

    一.常用表单标签如下: (1)<input>中的“type”属性: 复选框-checkbox:单选按钮-radio;按钮-button:提交-submit; (2)文本域 行-cols:列 ...

  8. UILabel 添加图片

    //设置显示图片 NSMutableAttributedString * cellAttributeStr = [[NSMutableAttributedString alloc]initWithSt ...

  9. IntelliJ IDEA gradle 创建 Java web 应用

    1.如下图,第一步很简单的,File->New->Project 2.在左边栏目找到Gradle,然后在右边勾选Java 和web 两个选项,next.如果只是Java项目就只选java就 ...

  10. SQL Server Logical/Physical Reads

    Summary Info: Logical Reads :    Reading Data pages from CachePhysical Reads :    Reading Data pages ...