HDU4888 Redraw Beautiful Drawings(最大流唯一性判定:残量网络删边判环)
题目
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(最大流唯一性判定:残量网络删边判环)的更多相关文章
- hdu4888 Redraw Beautiful Drawings 最大流+判环
hdu4888 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/6553 ...
- 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 ...
- hdu 4888 Redraw Beautiful Drawings(最大流,判环)
pid=4888">http://acm.hdu.edu.cn/showproblem.php?pid=4888 加入一个源点与汇点,建图例如以下: 1. 源点 -> 每一行相应 ...
- hdu4888 Redraw Beautiful Drawings(最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4888 题意:给一个矩阵没行的和和每列的和,问能否还原矩阵,如果可以还原解是否唯一,若唯一输出该矩阵. ...
- hdu 4888 Redraw Beautiful Drawings 最大流
好难好难,将行列当成X和Y,源汇点连接各自的X,Y集,容量为行列的和,相当于从源点流向每一行,然后分配流量给每一列,最后流入汇点,这样执意要推断最后是否满流,就知道有没有解,而解就是每一行流向每一列多 ...
- hdu4888 Redraw Beautiful Drawings
14更多学校的第二个问题 网络流量 分别以行,列作为结点建图 i行表示的结点到j列表示的结点的流量便是(i, j)的值 跑遍最大流 若满流了便是有解 推断是否unique 就是在残余网络 ...
- 最小割最大流定理&残量网络的性质
最小割最大流定理的内容: 对于一个网络流图 $G=(V,E)$,其中有源点和汇点,那么下面三个条件是等价的: 流$f$是图$G$的最大流 残量网络$G_f$不存在增广路 对于$G$的某一个割$(S,T ...
- Redraw Beautiful Drawings(hdu4888)网络流+最大流
Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/O ...
- HDU 4888 Redraw Beautiful Drawings(最大流+判最大流网络是否唯一)
Problem Description Alice and Bob are playing together. Alice is crazy about art and she has visited ...
随机推荐
- [转] C++的STL库,vector sort排序时间复杂度 及常见容器比较
http://www.169it.com/article/3215620760.html http://www.cnblogs.com/sharpfeng/archive/2012/09/18/269 ...
- JDBC之SqlHelper
SqlHelper工具类如下: import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Resul ...
- Cannot return from outside a function or method
最近发现myeclipse10中有几处bug 比如: Cannot return from outside a function or method onClick="return chec ...
- How to increase TX Power Signal Strength of WiFi
转自:https://www.blackmoreops.com/2013/10/27/how-to-increase-tx-power-signal-strength-of-wifi/ This gu ...
- 重温WCF之发送和接收SOAP头(三)
SOAP头可以理解为一种附加信息,就是附加到消息正文的内容. 既然消息头是附加信息,那有啥用呢?你可别说,有时候还真有不少用处.举个例子,WCF的身份验证是不是很麻烦?还要颁发什么证书的(当然不是荣誉 ...
- 【PHP用户的错误日志】
将产生的错误保存在日志中的方法:使用error_log方法,其中,当日志类型是3的时候,下一个参数将会是日志文件的保存路径 使用示例: <?php function myerror($level ...
- shell test 數值 字符串 文件比較
數值比較 描述 n1 –eq n2 等於 n1 –gt n2 大於 n1 –ge n2 大於等於 n1 –lt n2 小於 n1 –le n2 小於等於 n1 –ne n2 不等於 字符串比較 ...
- android 相对布局里面的一些属性
一. 有关于RelativeLayout布局的一些属性 1. 相对于兄弟控件的位置:android:layout_below Android:layout_toLeftof Android:la ...
- Win10 启动模拟器
不知道怎么解决 答:去bios里设置了.开启了虚拟化hyper,重启.
- long和int的区别
转自:http://blog.sina.com.cn/s/blog_6f62c9510101svjz.html 突然间就想到了long和int到底什么区别(发现有很多问题都是突然间想到的),然后百度. ...