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. MVC3中几个小知识点

    1.ViewBag.Name~ViewBag.name等价,即不区分大小写.在此小心,下次见到不要奇怪,不过最好还是写成一样的比较好. 2.JS字符串不允许有换行符,\'等字符,需提前处理.

  2. Java程序设计的基本原则

    Java程序设计的基本原则-1 1.面向对象 这是java编程里面大家公认的第一原则 2.优先使用对象组合而非类继承 3.分层 最典型的三层架构,表现层-->逻辑层-->数据层 表现层功能 ...

  3. sql性能优化小技巧(一)

    关于sql条件匹配对执行效率影响测试 首先,创建一个标量函数create function ff_test() returns int as begin declare @i int=0 while( ...

  4. .Net程序员安卓学习之路2:访问网络API

    做应用型的APP肯定是要和网络交互的,那么本节就来实战一把Android访问网络API,还是使用上节的DEMO: 一.准备API: 一般都采用Json作为数据交换格式,目前各种语言均能输出Json串. ...

  5. 关于前后台交互生成json区别

    如何返回[object{xx:{}}]这种数组型json在服务器端return $arr[]=m;像这种都可以产生[Object { 0="9", 1="8", ...

  6. 去除undefined和末尾逗号及把字符串数字转成数字数组的方法

    function removeundefined(str){   var v=new Array(),b="";   var tmp=fil(str); for(var i=0;i ...

  7. 面向对象分析方法(I)

    找出最关键的一些业务场景:一般通过动词来寻找,比如招聘系统中,一个应聘人投递一个职位就是一次应聘,应聘就是一个业务场景:一个学生参加某门课的考试,那么考试就是一个业务场景:一个学生去图书馆借书,那么借 ...

  8. Asset Store

    Asset Store 是用来供Unity开发者将自己的插件拿出来供大家有偿使用的一个平台. 报错信息: failed to import package with error cannot impo ...

  9. Fiddler-002-常用配置修改

    日常在应用 Fiddler 进行网络抓包时,有时需要查看服务器的类型或者其他信息,此文主要讲述实际应用中针对 Fiddler 进行的定制化配置,以方便日常的工作学习. 第一:显示服务器的类型和请求域名 ...

  10. Apple Demo

    https://developer.apple.com/library/ios/navigation/ http://developer.apple.com/library/ios/samplecod ...