题目链接

一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图。

首先对行列建边, 源点向行建边, 权值为这一行的和, 列向汇点建边, 权值为列和, 每一行向每一列建边, 权值为k, 因为上限是k。

然后跑一遍最大流, 如果最大流和所有行的和以及所有列的和相等, 那么可以还原。

判断是否唯一, 用判环的方式, 对图中每一个点dfs, 如果存在环, 说明原图不唯一。

原图每个格子的值等于k-这个格子的行与列之间的那条边的权值。

 #include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, a, n) for(int i = a; i<n; i++)
#define ull unsigned long long
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
const int maxn = 1e6+;
int q[maxn*], head[maxn*], dis[maxn/], s, t, num, vis[], cnt, col[], row[], g[][];
struct node
{
int to, nextt, c;
node(){}
node(int to, int nextt, int c):to(to), nextt(nextt), c(c){}
}e[maxn*];
void init() {
num = cnt = ;
mem1(head);
mem(vis);
}
void add(int u, int v, int c) {
e[num] = node(v, head[u], c); head[u] = num++;
e[num] = node(u, head[v], ); head[v] = num++;
}
int bfs() {
mem(dis);
dis[s] = ;
int st = , ed = ;
q[ed++] = s;
while(st<ed) {
int u = q[st++];
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(!dis[v]&&e[i].c) {
dis[v] = dis[u]+;
if(v == t)
return ;
q[ed++] = v;
}
}
}
return ;
}
int dfs(int u, int limit) {
if(u == t) {
return limit;
}
int cost = ;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(e[i].c&&dis[v] == dis[u]+) {
int tmp = dfs(v, min(limit-cost, e[i].c));
if(tmp>) {
e[i].c -= tmp;
e[i^].c += tmp;
cost += tmp;
if(cost == limit)
break;
} else {
dis[v] = -;
}
}
}
return cost;
}
int dinic() {
int ans = ;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
int dfs1(int u, int fa) {
if(vis[u])
return ;
vis[u] = ;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(v==fa||v==s||v==t) {
continue;
}
if(e[i].c) {
if(dfs1(v, u))
return ;
}
}
vis[u] = ;
return ;
}
int main()
{
int n, m, x, limit;
while(~scanf("%d%d%d", &n, &m, &limit)) {
init();
int sum1 = , sum2 = ;
s = , t = n+m+;
for(int i = ; i<=n; i++) {
scanf("%d", &x);
add(s, i, x);
sum2+=x;
for(int j = ; j<=m; j++) {
add(i, j+n, limit);
}
}
for(int i = ; i<=m; i++) {
scanf("%d", &x);
add(i+n, t, x);
sum1+=x;
}
int ans = dinic(), flag = ;
if(ans != sum1 || sum2!=ans) {
puts("Impossible");
continue;
}
for(int i = ; i<=n; i++) {
if(dfs1(i, -)) {
flag = ;
break;
}
}
if(flag) {
puts("Not Unique");
continue;
}
for(int u = ; u<=n; u++) {
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(v>n&&v<=n+m) {
g[u][v-n] = limit-e[i].c;
}
}
}
puts("Unique");
for(int i = ; i<=n; i++) {
for(int j = ; j<m; j++) {
printf("%d ", g[i][j]);
}
printf("%d\n", g[i][m]);
}
}
return ;
}

hdu 4888 Redraw Beautiful Drawings 网络流的更多相关文章

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

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

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

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

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

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

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

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

  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

    网络流. $s$向每一个$r[i]$连边,容量为$r[i]$. 每一个$r[i]$向每一个$c[j]$连边,容量为$k$. 每一个$c[j]$向$t$连边容量为$c[j]$. 跑最大流,中间每一条边上 ...

  7. hdu 4888 Redraw Beautiful Drawings 最大流

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

  8. hdu 4888 2014多校第三场1002 Redraw Beautiful Drawings 网络流

    思路:一開始以为是高斯消元什么的.想让队友搞,结果队友说不好搞,可能是网络流.我恍然,思路立刻就有了. 我们建一个二部图.左边是行,右边是列,建个源点与行建边,容量是该行的和.列与新建的汇点建边.容量 ...

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

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

随机推荐

  1. MongoDB无法启动的解决方法

    http://dmyz.org/archives/423 遇到MongoDB突然无法启动,第一反应是删除mongod.lock.这个文件在MongoDB的数据库目录下,默认是/data/db.这是最常 ...

  2. cdh 上安装spark on yarn

    在cdh 上安装spark on yarn 还是比较简单的,不需要独立安装什么模块或者组件. 安装服务 选择on yarn 模式:上面 Spark 在spark 服务中添加 在yarn 服务中添加 g ...

  3. NOIP第二次模拟赛 stage1【划分数列(seq.pas/c/cpp)

    7划分数列(seq.pas/c/cpp) [题目描述] 给你一个有n个元素的数列,要求把它划分成k段,使每段元素和的最大值最小 [输入格式] 第一行两个正整数n,k 第二行为此数列ai [输出格式] ...

  4. 浅谈C中的指针和数组(五)

    前面写了一些C指针和数组的一些知识,但是还有一些很重要的知识没有交代,这里做一个补充. 首先看一下,普通变量(指针也是变量)和数组名查看地址的方式是不同的. 查看数组变量的地址,不需要使用 & ...

  5. error2

         10:09:40 贾老师,请问这个错在哪里啊! ^^Li_Jia^^ 10:27:41 你第2个for的n是做什么的    10:28:06 换行 ^^Li_Jia^^ 10:28:26 这 ...

  6. Swift 基本数据类型

    Swift 1,Swift支持所有C和Objective-C的基本类型,支持面向过程和面向对象的编程机制. 2,Swift提供了两种功能强劲的集合类型:数组和字典. 3,元组. 4,可选类型. 5,S ...

  7. Python进阶之decorator装饰器

    decorator装饰器 .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB&quo ...

  8. Android学习笔记27:网格视图GridView的使用

    网格视图GridView的排列方式与矩阵类似,当屏幕上有很多元素(文字.图片或其他元素)需要按矩阵格式进行显示时,就可以使用GridView控件来实现. 本文将以一个具体的实例来说明如何使用GridV ...

  9. python 连接数据库-设置oracle ,mysql 中文字符问题

    import cx_Oracle import MySQLdb def conn_oracle(): cnn = cx_Oracle.connect('用户名','密码','ip:端口号/数据库') ...

  10. JAVA之Exchanger

    如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使用的空间,就需要用到Exchanger这个类,Exchanger为线程交换信息提供了非常方便的途径,它可以作为两个线程交换对象的同步点,只 ...