HDUOJ--4888--Redraw Beautiful Drawings【isap】网络流+判环
链接:http://acm.hdu.edu.cn/showproblem.php?
pid=4888
题意:一个矩阵。限定每行行和、列和,每一个格子数字不超过k,问矩阵是否存在,如存在推断有单解还是多解。
思路:之前多校的题目,那时候还不会网络流,如今A掉了,矩阵的建图模型,推断网络流是否可行仅仅要推断最大流是否等于总行和或总列和就可以,判环是看的别人的解题报告,方法是使用dfs查找残余网络中是否有还存在容量的弧形成了环,假设有,说明能够通过这个环改变容量网络内部的增广路方式。而源汇的流量是不会变的。就说明存在多解。假设没有环,就是单一解。
建图:源点向每一个行节点连弧,容量为该行行和,每一个列节点向汇点连边,容量为每一个列和,每一个行节点与每一个列节点之间连边,容量为k。
细节:之前WA了,我以为是minm赋值的问题,实际上minm赋值为nn-1是没问题的,仅仅要赋值大于等于nn-1即可了。WA的地方在dist[i]=-1时须要特判。统计层次时对-1不会统计,假设不加推断,会使数组下标变成-1,就错了。HDU上不是RE。是WA。之前一直没加过也AC了两题,如今知道了。
#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 50100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define LLINF 0x7FFFFFFFFFFFFFFF
#define seed 131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 struct node{
int u,v,w,next;
}edge[500000];
int head[820],dist[820],cur[820],fa[820],num[820],vis[820];
int n,m,k,cnt,nn,src,sink;
void add_edge(int a,int b,int c){
edge[cnt].u = a;
edge[cnt].v = b;
edge[cnt].w = c;
edge[cnt].next = head[a];
head[a] = cnt++;
}
void bfs()
{
int x,i,j;
queue<int> q;
memset(dist,-1,sizeof(dist));
q.push(sink);
dist[sink] = 0;
while(!q.empty()){
x = q.front();
q.pop();
for(i=head[x];i!=-1;i=edge[i].next){
if(dist[edge[i].v]<0){
dist[edge[i].v] = dist[x] + 1;
q.push(edge[i].v);
}
}
}
} int augment()
{
int x=sink,a=INF;
while(x!=src){
a = min(a,edge[fa[x]].w);
x = edge[fa[x]].u;
}
x=sink;
while(x!=src){
edge[fa[x]].w -= a;
edge[fa[x]^1].w += a;
x = edge[fa[x]].u;
}
return a;
} int isap()
{
int i,x,ok,minm,flow=0;
memset(num,0,sizeof(num));
bfs();
for(i=0;i<=nn+5;i++) if(dist[i]!=-1) num[dist[i]]++;
for(i=0;i<=nn+5;i++) cur[i] = head[i];
x=src;
while(dist[src]<nn){
if(x==sink){
flow += augment();
x = src;
}
ok=0;
for(i=cur[x];i!=-1;i=edge[i].next){
if(edge[i].w && dist[x]==dist[edge[i].v]+1){
ok=1;
fa[edge[i].v] = i;
cur[x] = i;
x = edge[i].v;
break;
}
}
if(!ok){
minm = nn - 1;
for(i=head[x];i!=-1;i=edge[i].next)
if(edge[i].w && dist[edge[i].v]<minm) minm=dist[edge[i].v];
if(--num[dist[x]]==0)break;
num[dist[x]=minm+1]++;
cur[x]=head[x];
if(x!=src) x=edge[fa[x]].u;
}
}
return flow;
}
bool dfs(int u,int pre){
int i,j;
if(vis[u]) return true;
vis[u] = 1;
for(i=head[u];i!=-1;i=edge[i].next){
if(edge[i].w>0&&edge[i].v!=pre&&dfs(edge[i].v,u))
return true;
}
vis[u] = 0;
return false;
}
int row[410],col[410];
int ans[420][420];
int main(){
int i,j;
int sumr,sumc;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
memset(head,-1,sizeof(head));
sumr = sumc = 0;
cnt = 0;
src = 0;
sink = n + m + 1;
nn = sink + 1;
for(i=1;i<=n;i++){
scanf("%d",&row[i]);
sumr += row[i];
add_edge(src,i,row[i]);
add_edge(i,src,0);
for(j=1;j<=m;j++){
add_edge(i,j+n,k);
add_edge(j+n,i,0);
}
}
for(i=1,j=n+1;i<=m;j++,i++){
scanf("%d",&col[i]);
sumc += col[i];
add_edge(j,sink,col[i]);
add_edge(sink,j,0);
}
if(sumr!=sumc){
puts("Impossible");
continue;
}
int flag = 0;
int flow = isap();
if(flow!=sumr){
puts("Impossible");
continue;
}
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++){
if(dfs(i,-1)){
flag = 1;
break;
}
}
if(flag){
puts("Not Unique");
continue;
}
puts("Unique");
memset(ans,0,sizeof(ans));
for(i=1;i<=n;i++){
for(j=head[i];j!=-1;j=edge[j].next){
int u = edge[j].v;
if(u>n&&u<=n+m){
ans[i][u-n] = k - edge[j].w;
}
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(j>1) printf(" ");
printf("%d",ans[i][j]);
}
printf("\n");
}
}
return 0;
}
HDUOJ--4888--Redraw Beautiful Drawings【isap】网络流+判环的更多相关文章
- hdu4888 Redraw Beautiful Drawings 最大流+判环
hdu4888 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/6553 ...
- 【HDU】4888 Redraw Beautiful Drawings 网络流【推断解是否唯一】
传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因 ...
- hdu 4888 Redraw Beautiful Drawings 网络流
题目链接 一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图. 首先对行列建边, 源点向行 ...
- HDU 4888 Redraw Beautiful Drawings(最大流+判最大流网络是否唯一)
Problem Description Alice and Bob are playing together. Alice is crazy about art and she has visited ...
- HDU 4888 Redraw Beautiful Drawings 网络流 建图
题意: 给定n, m, k 以下n个整数 a[n] 以下m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵.若有多解输出Not Unique,若无解输出Impossib ...
- hdu 4888 Redraw Beautiful Drawings(最大流,判环)
pid=4888">http://acm.hdu.edu.cn/showproblem.php?pid=4888 加入一个源点与汇点,建图例如以下: 1. 源点 -> 每一行相应 ...
- HDU 4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)
题意:给定n*m个格子,每个格子能填0-k 的整数.然后给出每列之和和每行之和,问有没有解,有的话是不是唯一解,是唯一解输出方案. 思路:网络流,一共 n+m+2个点 源点 到行连流量为 所给的 ...
- HDU 4888 Redraw Beautiful Drawings
网络流. $s$向每一个$r[i]$连边,容量为$r[i]$. 每一个$r[i]$向每一个$c[j]$连边,容量为$k$. 每一个$c[j]$向$t$连边容量为$c[j]$. 跑最大流,中间每一条边上 ...
- hdu 4888 Redraw Beautiful Drawings 最大流
好难好难,将行列当成X和Y,源汇点连接各自的X,Y集,容量为行列的和,相当于从源点流向每一行,然后分配流量给每一列,最后流入汇点,这样执意要推断最后是否满流,就知道有没有解,而解就是每一行流向每一列多 ...
- Redraw Beautiful Drawings(hdu4888)网络流+最大流
Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/O ...
随机推荐
- iOS开发之KVC全解
一 KVC的基本概念 1.KVC是Key Value Coding的缩写,意思是键值编码. 在iOS中,提供了一种方法通过使用属性的名称(也就是Key)来间接访问对象属性的方法,这个方法可以不通过g ...
- lowbit( )运算
--------开始-------- lowbit (n) 定义为非负整数n在二进制表示下“最低位的1及其后面所有的0构成的数值. 比如: n = 10 的二进制下为1010,则lowbit (n) ...
- C# 标准命名规范
笔者从事开发多年,有这样一种感觉,查看一些开源项目,如Spring.Apache Common等源码是一件赏心悦目的事情,究其原因,无外两点:1)代码质量非常高:2)命名特别规范(这可能跟老外的英语水 ...
- System.net.mail发送电子邮件
之前做的实现发送邮件的功能,基于System.net.mail,在本地测试是可以发送邮件的,发布到服务器上发送不了邮件,后来发现STMP默认使用25端口收发邮件,服务器封掉25了端口,导致发送邮件失败 ...
- P3709 大爷的字符串题(50分)
题目背景 在那遥远的西南有一所学校 /*被和谐部分*/ 然后去参加该省省选虐场 然后某蒟蒻不会做,所以也出了一个字符串题: 题目描述 给你一个字符串a,每次询问一段区间的贡献 贡献定义: 每次从这个区 ...
- unicode、UTF-8、UTF-16的历史
1:中国人民通过对 ASCII 编码的中文扩充改造,产生了 GB2312 编码,可以表示6000多个常用汉字. 2:汉字实在是太多了,包括繁体和各种字符,于是产生了 GBK 编码,它包括了 GB231 ...
- Deutsch lernen (03)
1. das Gewerbe, - 行业 Was ist Ihr Gewerbe? Welches Gewerbe treibt er? treiben - trieb - getrieben 从事 ...
- OpenCv:椭圆上点的计算方程
椭圆 椭圆(Ellipse)是平面内到定点F1.F2的距离之和等于常数(大于|F1F2|)的动点P的轨迹,F1.F2称为椭圆的两个焦点.其数学表达式为: ...
- OpenCv: 二维坐标的旋转方程
1. 可以写成一个矩阵的形式,也可以写成向量的形式: b 为选转角度加pi/2 x1 = x cos(b) - ysin(b) ; y1 = x sin(b) + y cos(b).
- eas之日期选择控件
初始化打印控件KDPrinter ctrlPrinter = new KDPrinter(); 增加列 // 指定插入位置table.addColumn(index);// 插入到最后table.ad ...