思路:一開始以为是高斯消元什么的。想让队友搞,结果队友说不好搞,可能是网络流。我恍然,思路立刻就有了。

我们建一个二部图。左边是行,右边是列,建个源点与行建边,容量是该行的和。列与新建的汇点建边。容量是该列的和,最后每行与每列建边,容量为题意中的k。建边如图:







跑一遍最大流,假设最大流等于行的和且等于列的和,那么就是有解的,否则无解。这样我们得到了一组解,行i到列j的流量即为i行j列的大小。之后便是推断是否有多种情况了。

基本思路是这种,我们看下图:





有多解的情况一定能够找到这种4个位置:AB同行。CD同行。AC同列。BD同列。而且他们符合一下两种情况的当中一种:

1、AD未达到k(可变大)。BC不是0(可减小)

2、AD不是0(可减小)。BC未达到k(可变大)

只是枚举的话复杂度太高了。这里须要优化下。我建了一个二维数组cc[i][j],代表之前行是否有第i个可变大,第j个可减小的情况。这里枚举每一行,每一行再枚举两个位置i和j,假设当前行有i和j使得第i能够减小、第j个能够变大而且cc[i][j]为1,那么一定有多解。这里假设cc[i][j]为0。那么继续。同一时候cc[j][i]赋为1。这种话就避免了最坏O(400^4)的复杂度。而变成了最多O(400^3)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#define maxn 1<<29
using namespace std;
struct edge
{
int from,to,cap,flow;
};
vector<int>g[888];
vector<edge>edges;
int m,n,ma;
bool vis[888];
int d[888];
int cur[888];
int fl[444][444];
bool cc[444][444];
void init()
{
edges.clear();
int mm=m+n+1;
for(int i=0;i<=mm;i++)g[i].clear();
}
void add(int u,int v,int c)
{
edges.push_back((edge){u,v,c,0});
g[u].push_back(edges.size()-1);
edges.push_back((edge){v,u,0,0});
g[v].push_back(edges.size()-1);
}
bool bfs(int s,int t)
{
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
int size=g[u].size();
for(int i=0;i<size;i++)
{
edge &e=edges[g[u][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[u]+1;
q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int u,int t,int mi)
{
if(u==t||mi==0)return mi;
int flow=0,f;
int size=g[u].size();
for(int &i=cur[u];i<size;i++)
{
edge &e=edges[g[u][i]];
if(d[u]+1==d[e.to]&&(f=dfs(e.to,t,min(mi,e.cap-e.flow)))>0)
{
e.flow+=f;
edges[g[u][i]^1].flow-=f;
flow+=f;
mi-=f;
if(mi==0)break;
}
}
return flow;
}
int dinic(int s,int t)
{
int flow=0;
while(bfs(s,t))
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,t,maxn);
}
return flow;
}
bool go()
{
for(int i=1;i<=n;i++)
{
int size=g[i].size();
for(int j=0;j<size;j++)
{
edge &e=edges[g[i][j]];
if(e.to>n&&e.to<=m+n)
{
//cout<<e.from<<" "<<e.to<<" "<<e.flow<<endl;
fl[i][e.to-n]=e.flow;
}
}
}
memset(cc,0,sizeof(cc));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=j+1;k<=m;k++)
{
bool v1=0,v2=0;
if(fl[i][j]!=ma&&fl[i][k]!=0)
{
if(cc[k][j])return true;
v1=1;
}
if(fl[i][j]!=0&&fl[i][k]!=ma)
{
if(cc[j][k])return true;
v2=1;
}
if(v1)cc[j][k]=1;
if(v2)cc[k][j]=1;
}
}
}
return false;
}
int main()
{
int u,v,c;
int s1,s2;
while(scanf("%d%d%d",&n,&m,&ma)!=EOF)
{
init();
s1=s2=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&c);
add(0,i,c);
s1+=c;
for(int j=1;j<=m;j++)
{
add(i,n+j,ma);
}
}
for(int i=1;i<=m;i++)
{
scanf("%d",&c);
add(n+i,m+n+1,c);
s2+=c;
}
int ans=dinic(0,m+n+1);
if(ans!=s1||ans!=s2)printf("Impossible\n");
else if(go())printf("Not Unique\n");
else
{
printf("Unique\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%d",fl[i][j]);
if(j==m)printf("\n");
else printf(" ");
}
}
}
}
return 0;
}

hdu 4888 2014多校第三场1002 Redraw Beautiful Drawings 网络流的更多相关文章

  1. 【HDU】4888 Redraw Beautiful Drawings 网络流【推断解是否唯一】

    传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因 ...

  2. 2014多校第三场1005 || HDU 4891 The Great Pan(模拟)

    题目链接 题意 : 给你n行字符串,问你有多少种理解方式.有两大类的理解 (1){A|B|C|D|...}代表着理解方式可以是A,可以是B或C或者D. (2)$blah blah$,在$$这两个符号中 ...

  3. hdu-4893-Wow! Such Sequence!-线段树【2014多校第三场-J】

    题意:一个初始为0的数组,支持三种操作:1.向第k个数添加d,(|d| < 2^31);2.把[l, r]区间内的数字都换成与它最相近的Fibonacci数;3.询问[l, r]区间的和. 思路 ...

  4. 2014多校第十场1002 || HDU 4972 A simple dynamic programming problem

    题目链接 题意 : 每次无论哪个队投进一个篮球,就记下现在两队比分的差值,问你最后的结果有多少种情况. 思路 : 该题实在是不好理解,最后的结果有多少种情况就是说不管中间过程怎么来的,只要最后结果不一 ...

  5. HDU 4622 多校第三场1002 后缀自动机

    比赛的时候我是用后缀数组的,但是T了. 赛后看了解题报告说,后缀数组貌似是卡你常数的时间,我算了下复杂度O(T * Q * n).这是10 ^ 8,但是考虑到每次询问的时候都要重新构造字符,所以那个n ...

  6. hdu 4888 Redraw Beautiful Drawings 网络流

    题目链接 一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图. 首先对行列建边, 源点向行 ...

  7. HDU 4888 Redraw Beautiful Drawings 网络流 建图

    题意: 给定n, m, k 以下n个整数 a[n] 以下m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵.若有多解输出Not Unique,若无解输出Impossib ...

  8. 2018 HDU多校第三场赛后补题

    2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...

  9. hdu 5288||2015多校联合第一场1001题

    pid=5288">http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a ar ...

随机推荐

  1. STEM教育是什么?

    STEM教育是什么? STEM 是Science科学.Technology技术.Engineering工程.Math数学,这4个词的开头字母的组合.所以STEM教育就是结合科学.技术.工程.数学的跨领 ...

  2. 【撸码caffe 二】 blob.hpp

    Blob类是caffe中对处理和传递的实际数据的封装,是caffe中基本的数据存储单元,包括前向传播中的图像数据,反向传播中的梯度数据以及网络层间的中间数据变量(包括权值,偏置等),训练模型的参数等等 ...

  3. 【转】iOS程序自动检测更新的实现 -- 思路不错

    原文网址:http://blog.csdn.net/davidsph/article/details/8931718 之前项目需要用到app自动更新的功能,现将实现方案分享出来.iOS程序自动提示更新 ...

  4. 第17章 Redis概述

    17.2.1 在Windows下安装Redis https://github.com/ServiceStack/redis-windows/tree/master/downloads redis-se ...

  5. [专辑] 也晒晒我的RBAC系统 ——行一山人的博客

    也晒晒我的RBAC系统(一):概述 也晒晒我的RBAC系统(二):系统实现原理简介 也晒晒我的RBAC系统(三):后台管理程序源码及使用演示 也晒晒我的RBAC系统(四):框架源代码(超值奉献,请勿拍 ...

  6. Java中利用随机数的猜拳游戏

    Java中利用随机数的猜拳游戏,实现非常简单,重难点在于随机数的产生. 首先GameJude类是用于判断输赢的一个类: package testGame; public class GameJudge ...

  7. VM虚拟机-Windows

    前提:安装了vm虚拟机 一.下载win10原版镜像文件 一定要是原版,修改版的不能用. 推荐下载网址:http://www.xitongtiandi.net/win10yuanban/ 下载后放在D盘 ...

  8. Windows 下修改 MySQL 编码为 utf8

    问题 Windows 下安装 MySQL 后,默认编码不全utf8. mysql> show variables like '%char%'; +------------------------ ...

  9. sphinx with discuz

    安装sphinx: sudo apt-get install sphinxsearch 配置: source discuz { type = mysql sql_host = xx.xx.xx.xx ...

  10. Python学习笔记基础篇-(1)Python周边

    一.系统命令 1.Ctrl+D 退出Python IDLE input方法中输入EOF字符,键入Ctrl+D 2.命令行选项: -d   提供调试输出 -O 生成优化的字节码(.pyo文件) -S 不 ...