题目

Source

http://acm.hdu.edu.cn/showproblem.php?pid=4888

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).

Sample Input

2 2 4
4 2
4 2
4 2 2
2 2 5 0
5 4
1 4 3
9
1 2 3 3

Sample Output

Not Unique
Impossible
Unique
1 2 3 3

分析

题目大概说有一个矩阵,已知各个单元的值在0到k之间以及各行各列的和,要求还原该矩阵,如果唯一的话就输出解。

经典的构图了吧,POJ2396

  • 把行、列看成点,各单元看成边

而问题关键在于判定最大流唯一性。

这个结论是,残量网络不存在环是最大流唯一的充要条件。找到环绕着一圈调整一下环上边的流量,比如流量-1(同时对应的反向边或者正向边流量+1),这样又会是一个满足平衡条件的最大流。

在残量网络中找环,不能用拓扑排序。因为正向边和反向边应该要看成一体,即如果统计了正向边贡献的出入度,那么反向边的出入度就不需要统计了,反之亦然,而我们没法确定各边是选正向还是反向。

那么环就用搜索找了:

bool dfs(int u,int fa){
vis[u]=1;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(v==fa || edge[i].cap==edge[i].flow) continue;
if(vis[v]) return 1;
if(dfs(v,u)) return 1;
}
vis[u]=0;
return 0;
}

不过这个怎么看都是指数级时间复杂度。

我在这个博客看到了删边的做法。确实,回溯后说明往当前这条边走是找不到环的,以后不必要再往这条边走,这样每条边最多都只走一次就保证了时间复杂度为多项式级别的了。

不过我看不懂那个博客的删边方式,我就比较low地标记删除的边,遇到被标记的就跳过。。不过这么做HDU4975是TLE的;于是我就自己想了想怎么真正地删边,然后实现了下,还是TLE,这不是线性时间复杂度了吗?。。好吧那题我选择放弃。

另外还有一个可以优化的是枚举环的起点只要枚举容量网络中行对应的点,我大概想了下是因为这题建图方式构成了二分图,那样从列对应的点出发找到环一定是会经过行对应的点的,于是从行对应的点出发也能形成这个环。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 888
#define MAXM 444*888 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-1) continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^1].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0) break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
} bool vis[MAXN]; bool dfs(int u,int fa){
vis[u]=1;
for(int i=head[u],pre=i; i!=-1; ){
int v=edge[i].v;
if(v==fa || edge[i].cap==edge[i].flow){
pre=i;
i=edge[i].next;
continue;
}
if(vis[v]) return 1;
if(dfs(v,u)) return 1;
if(i==head[u]){
i=edge[i].next;
head[u]=i;
}else{
i=edge[i].next;
edge[pre].next=i;
}
}
vis[u]=0;
return 0;
} int ans[444][444]; int main(){
int n,m,k,a;
while(~scanf("%d%d%d",&n,&m,&k)){
vs=0; vt=n+m+1; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
int row=0,col=0;
for(int i=1; i<=n; ++i){
scanf("%d",&a);
addEdge(vs,i,a);
row+=a;
}
for(int i=1; i<=m; ++i){
scanf("%d",&a);
addEdge(i+n,vt,a);
col+=a;
}
if(row!=col){
puts("Impossible");
continue;
}
for(int i=1; i<=n; ++i){
for(int j=1; j<=m; ++j){
addEdge(i,j+n,k);
}
}
if(ISAP()!=row){
puts("Impossible");
continue;
}
for(int u=1; u<=n; ++u){
for(int i=head[u]; i!=-1; i=edge[i].next){
if(i&1) continue;
int v=edge[i].v-n;
ans[u][v]=edge[i].flow;
}
}
bool flag=1;
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; ++i){
if(dfs(i,i)){
flag=0;
break;
}
}
if(!flag){
puts("Not Unique");
continue;
}
puts("Unique");
for(int i=1; i<=n; ++i){
for(int j=1; j<=m; ++j){
if(j!=1) putchar(' ');
printf("%d",ans[i][j]);
}
putchar('\n');
}
}
return 0;
}

HDU4888 Redraw Beautiful Drawings(最大流唯一性判定:残量网络删边判环)的更多相关文章

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

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

  2. HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

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

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

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

  4. hdu4888 Redraw Beautiful Drawings(最大流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4888 题意:给一个矩阵没行的和和每列的和,问能否还原矩阵,如果可以还原解是否唯一,若唯一输出该矩阵. ...

  5. hdu 4888 Redraw Beautiful Drawings 最大流

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

  6. hdu4888 Redraw Beautiful Drawings

    14更多学校的第二个问题 网络流量   分别以行,列作为结点建图 i行表示的结点到j列表示的结点的流量便是(i, j)的值 跑遍最大流   若满流了便是有解   推断是否unique  就是在残余网络 ...

  7. 最小割最大流定理&残量网络的性质

    最小割最大流定理的内容: 对于一个网络流图 $G=(V,E)$,其中有源点和汇点,那么下面三个条件是等价的: 流$f$是图$G$的最大流 残量网络$G_f$不存在增广路 对于$G$的某一个割$(S,T ...

  8. Redraw Beautiful Drawings(hdu4888)网络流+最大流

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

  9. HDU 4888 Redraw Beautiful Drawings(最大流+判最大流网络是否唯一)

    Problem Description Alice and Bob are playing together. Alice is crazy about art and she has visited ...

随机推荐

  1. 安装less

    1.下载安装iterm(http://www.iterm2.com/) 2.打开iterm,输入 sudo npm install -g less

  2. Jmeter 函数

    一._csvRead 函数 _cvsRead函数是从外部读取参数,csvRead函数可以从一个文件中读取多个参数. 步骤: 1.先新建一个文件,例如c.txt,里面的数据存放为 web@qq.com, ...

  3. samba 最简单配置 共享

    [root@GitLab ~]# cat /etc/samba/smb.conf [global] workgroup = WORKGROUP server string = David Samba ...

  4. 与你相遇好幸运,CentOS 7 x86_64使用Yum安装PostgreSQL

    访问http://yum.pgrpms.org/reporpms/repoview/letter_p.group.html,下载并安装和当前系统对应的rpm文件. wget https://downl ...

  5. Faster-rnnlm代码分析1 - 词表构建,Nnet成员

    https://github.com/yandex/faster-rnnlm     Gdb ./rnnlm r -rnnlm model-good.faster -train thread.titl ...

  6. Sphinx的介绍和原理探索

    What/Sphinx是什么 定义 Sphinx是一个全文检索引擎. 特性 索引和性能优异 易于集成SQL和XML数据源,并可使用SphinxAPI.SphinxQL或者SphinxSE搜索接口 易于 ...

  7. PHP中比较两个时间的大小与日期的差值

    在这里我们全用到时间戳 mktime(hour,minute,second,month,day,year,[is_dst])     其参数可以从右向左省略,任何省略的参数都会被设置成本地日期和时间的 ...

  8. apache https配置步骤

    转自:http://www.cnblogs.com/best-jobs/p/3298258.html 1.  确认是否安装ssl模块 是否有mod_ssl.so文件 2.  生成证书和密钥 linux ...

  9. cocoaPads 安装及出现Analyzing dependencies之后卡死解决方案

    1.安装 a. 查看源 gem sources -l b. 设置源: sudo gem sources -a http://ruby.taobao.org c. 删除源:sudo gem source ...

  10. 遍历PspCidTable表检测隐藏进程

    一.PspCidTable概述 PspCidTable也是一个句柄表,其格式与普通的句柄表是完全一样的,但它与每个进程私有的句柄表有以下不同: 1.PspCidTable中存放的对象是系统中所有的进程 ...