题意:给定n*m个格子,每个格子能填0-k 的整数。然后给出每列之和和每行之和,问有没有解,有的话是不是唯一解,是唯一解输出方案。

思路:网络流,一共 n+m+2个点   源点 到行连流量为 所给的 当前行之和。    每行 连到每一列 一条流量为  k的边,每列到汇点连 列和。如果流量等于总和则有解,反之无解(如果列总和不等于行总和也无解)。  判断方案是否唯一 找残留网络是否存在长度大于2的环即可,有环说明不唯一。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include <iostream>
#include<climits>
using namespace std;
const int N = ;
const int M = ;
int n;
int ecnt, head[N], nx[M], to[M], va[M], cur_edge[N];
int source, target, flow, pre[N], lev[N], qu[N], sign;
void addedge(int u, int v, int w) {
to[ecnt] = v;
nx[ecnt] = head[u];
va[ecnt] = w;
head[u] = ecnt++;
}
bool bfs(int s, int t) {
std::fill(lev, lev + n, -);
sign = t;
lev[t] = ;
int st = , ed = ;
qu[ed++] = t;
while (st != ed && lev[s] == -) {
int u = qu[st++];
for (int i = head[u]; i != -; i = nx[i]) {
if (va[i ^ ] > && lev[to[i]] == -) {
lev[to[i]] = lev[u] + ;
qu[ed++] = to[i];
}
}
}
return lev[s] != -;
}
void push() {
int delta = INT_MAX, u, p;
for (u = target; u != source; u = to[p ^ ]) {
p = pre[u];
delta = std::min(delta, va[p]);
}
for (u = target; u != source; u = to[p ^ ]) {
p = pre[u];
va[p] -= delta;
if (!va[p]) {//注意double时要改
sign = to[p ^ ];
}
va[p ^ ] += delta;
}
flow += delta;
}
void dfs(int u) {
if (u == target)
push();
else {
for (int i = cur_edge[u]; i != -; i = nx[i]) {
if (va[i] > && lev[u] == lev[to[i]] + ) {
pre[to[i]] = i;
dfs(to[i]);
if (lev[sign] > lev[u]) {
return;
}
sign = target;
}
}
lev[u] = -;
}
}
void dinic(int s, int t, int node_cnt) {
source = s;
target = t;
n = node_cnt; //construct graph flow = ;
while (bfs(source, target)) {
for (int i = ; i < n; ++i) {
cur_edge[i] = head[i];
}
dfs(source);
} }
int nc, kc, mc, sum1, sum2;
int r[], c[];
void init() {
sum1 = sum2 = ;
for (int i = ; i < nc; ++i) {
scanf("%d", &r[i]);
sum1 += r[i];
}
for (int i = ; i < mc; ++i) {
scanf("%d", &c[i]);
sum2 += c[i];
}
}
int flag = ;
bool bo[];
bool bb[];
int cas[];
int ri = ;
void gao(int now, int fa) {//找环
if(flag)return;
//printf("->%d ",now);
bo[now] = true;
for (int i = head[now]; i != -; i = nx[i]) {
int u = to[i];
if (u == fa)
continue;
if (va[i] == )
continue; // printf(" {%d %d}\n",now,u);
if (bb[u]) {
// puts("fuck");
flag = ;
return;
}
if (cas[i] == ri)
continue;
cas[i] = ri;
//if(bo[u])continue;
bb[u] = true;
gao(u, now);
bb[u] = false;
}
}
void solve() {
if (sum1 != sum2) {
puts("Impossible");
return;
}
std::fill(head, head + mc + nc + , -);
ecnt = ;
int s, t;
s = nc + mc;
t = s + ;
// printf("st:%d %d\n",s,t);
for (int i = ; i < nc; ++i) {
for (int j = ; j < mc; ++j) { // printf("[%d %d]\n",i,j+nc);
addedge(i, j + nc, kc);
addedge(j + nc, i, );
}
}
for (int i = ; i < nc; ++i) {
// printf("[%d %d]\n",s,i);
addedge(s, i, r[i]);
addedge(i, s, );
}
for (int i = ; i < mc; ++i) { // printf("[%d %d]\n",i+nc,t);
addedge(i + nc, t, c[i]);
addedge(t, i + nc, );
}
dinic(s, t, t + );
// printf("flow:%d\n",flow);
if (flow == sum1) { memset(bo, , sizeof(bo));
memset(bb, , sizeof(bb));
flag = ;
for (int i = ; i <= t; ++i) {
if(flag)break;
bb[i] = true;
gao(i, -);
bb[i] = false;
}
if (flag)
puts("Not Unique");
else {
puts("Unique");
for (int i = ; i < nc; ++i) {
for (int j = ; j < mc; ++j) {
int now = i * mc + j;
printf("%d", va[now << | ]);
if (j == mc - )
puts("");
else
printf(" ");
}
}
}
} else
puts("Impossible");
}
int main() {
memset(cas, , sizeof(cas));
while (scanf("%d%d%d", &nc, &mc, &kc) != EOF) {
++ri;
init();
solve();
}
return ;
}

HDU 4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)的更多相关文章

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

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

  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. hdu 4888 Redraw Beautiful Drawings 网络流

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

  5. hdu 4888 Redraw Beautiful Drawings 最大流

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

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

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

  7. HDU 4888 Redraw Beautiful Drawings

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

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

    传送门:pid=4888">[HDU]4888 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. matplotlib库的常用知识

    看看matplotlib是什么? matplotlib是python上的一个2D绘图库,它可以在夸平台上边出很多高质量的图像.综旨就是让简单的事变得更简单,让复杂的事变得可能.我们可以用matplot ...

  2. 【Todo】Nginx架构学习

    要进行Web服务,绕不开的就是Nginx.这已经是大型网站的标配.对Nginx进行一定程度的深入学习. http://www.ituring.com.cn/article/4436 http://bl ...

  3. struct和class

    先概述一下: 1.C# 是纯面向对象语言,struct 与 class 都是继承Object,都是对象.struct 是值类型.class 是引用类型. 2.struct是值类型,在Stack上分配地 ...

  4. Sqlerver_各类函数

    SQL Aggregate 函数 SQL Aggregate 函数计算从列中取得的值,返回一个单一的值. 有用的 Aggregate 函数: AVG() - 返回平均值-SELECT AVG(colu ...

  5. jQuery数组的遍历 function的加载

    加载函数时会被覆盖在jQuery中给提供的方案有三种形式 js中只能绑定一个方法 如果多次绑定后者会覆盖前者 最常用的一种 在jQuery中数组的遍历 使用map遍历数组  会返回一个新的数组  如果 ...

  6. php imagecreatetruecolor输出字符符或验证码

    $img = imagecreatetruecolor(100,100); //创建真彩图像资源 $color = imagecolorAllocate($img,200,200,200); //分配 ...

  7. K-均值聚类及其在生物信息中的应用

    如果一点基础没有最好先拿起一本教材开始学,<机器学习实战>还不错,P93,书上有python源码和练习数据,非常适合新手. k均值聚类 名词:簇:相似度算法 伪代码 创建K个点作为起始质心 ...

  8. perl 语法速查

    同时学perl.python和shell脚本会很容易将它们的语法搞混,本文主要是一个个人的总结,方便要用时的查询. perl基本语法.安装.帮助文档 文件头格式: #!/usr/bin/perl us ...

  9. mydbtest文档

    mydbtest是楼方鑫编写的一个数据库测试工具,有需要的话,请自取 http://pan.baidu.com/s/1mgJpukg#path=%252FOneSQL%252FDocument 找到& ...

  10. c语言数据结构:递归的替代-------回溯算法

    1.要理解回溯就必须清楚递归的定义和过程. 递归算法的非递归形式可采用回溯算法.主要考虑的问题在于: 怎样算完整的一轮操作. 执行的操作过程中怎样保存当前的状态以确保以后回溯访问. 怎样返回至上一次未 ...