博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
有源汇上下界可行流(POJ2396)
阅读量:5343 次
发布时间:2019-06-15

本文共 2967 字,大约阅读时间需要 9 分钟。

题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案。

源点向行,汇点向列,连一条上下界均为和的边。

对于某格的限制,从它所在行向所在列连其上下界的边。

求有源汇上下界可行流即可。

具体做法可以从汇点向源点连容量为正无穷的边,转成无源汇上下界可行流。

然后可以新建超级源汇,对于一条下界为l,上界为r的边(x,y),从超级源点向y,x向超级汇点连容量为l的边,x向y连容量为r-l的边。

如果那些容量为l的边没满流,则无解。

#include 
#include
#include
#include
using namespace std;const int inf = 0x3f3f3f3f, N = 230, M = 25000;char op[2];int q,n,m,c,x,y,z,s,t,S,T,e=1,fr,l[205][25],r[205][25],ans[205][25],hd[N],nxt[M],to[M],f[M],ch[N];void add(int x, int y, int z) { to[++e] = y, f[e] = z, nxt[e] = hd[x], hd[x] = e; to[++e] = x, f[e] = 0, nxt[e] = hd[y], hd[y] = e;}void upd(int x, int y) { if(op[0] == '<') r[x][y] = min(r[x][y], z-1); else if(op[0] == '>') l[x][y] = max(l[x][y], z+1); else l[x][y] = max(l[x][y], z), r[x][y] = min(r[x][y], z);}bool tel() { memset(ch, -1, sizeof ch); queue
q; q.push(S), ch[S] = 0; while(!q.empty()) { int u = q.front(); q.pop(); for(int i = hd[u]; i; i = nxt[i]) if(ch[to[i]] == -1 && f[i]) ch[to[i]] = ch[u]+1, q.push(to[i]); } return ch[T] != -1;}int zng(int a, int b) { if(a == T) return b; int r = 0; for(int i = hd[a]; i && b > r; i = nxt[i]) if(ch[to[i]] == ch[a]+1 && f[i]) { int rr = zng(to[i], min(b-r, f[i])); f[i] -= rr, f[i^1] += rr, r += rr; } if(!r) ch[a] = -1; return r;}int main() { scanf("%d", &q); while(q--) { e = 1; memset(hd, 0, sizeof hd); memset(l, 0, sizeof l); memset(r, 0x3f, sizeof r); scanf("%d%d", &n, &m), t = n+m+1, S = n+m+2, T = n+m+3, add(t,s,inf); for(int i = 1; i <= n; i++) scanf("%d", &x), add(S,i,x), add(s,T,x); for(int i = 1; i <= m; i++) scanf("%d", &x), add(S,t,x), add(i+n,T,x); scanf("%d", &c); while(c--) { scanf("%d%d%s%d", &x, &y, op, &z); if(!x && !y) { for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) upd(i,j); } else if(!x) { for(int i = 1; i <= n; i++) upd(i,y); } else if(!y) { for(int i = 1; i <= m; i++) upd(x,i); } else upd(x,y); } if(fr) puts(""); fr = 1; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) { if(r[i][j] < l[i][j]) {puts("IMPOSSIBLE"); goto aa;} add(i,j+n,r[i][j]-l[i][j]),add(S,j+n,l[i][j]),add(i,T,l[i][j]); } while(tel()) while(zng(S,inf)); for(int i = hd[S]; i; i = nxt[i]) if(f[i]) {puts("IMPOSSIBLE"); goto aa;} for(int i = 1; i <= n; i++) for(int j = hd[i]; j; j = nxt[j]) if(to[j] > n && to[j] <= n+m) ans[i][to[j]-n] = f[j^1]; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) printf("%d%c", ans[i][j]+l[i][j], " \n"[j==m]); aa: ; } return 0;}

转载于:https://www.cnblogs.com/juruolty/p/6204025.html

你可能感兴趣的文章
如何在工作中快速成长?阿里资深架构师给工程师的10个简单技巧
查看>>
WebSocket 时时双向数据,前后端(聊天室)
查看>>
关于python中带下划线的变量和函数 的意义
查看>>
linux清空日志文件内容 (转)
查看>>
安卓第十三天笔记-服务(Service)
查看>>
Servlet接收JSP参数乱码问题解决办法
查看>>
【bzoj5016】[Snoi2017]一个简单的询问 莫队算法
查看>>
Ajax : load()
查看>>
MySQL-EXPLAIN执行计划Extra解释
查看>>
Zookeeper概述
查看>>
Zookeeper一致性级别
查看>>
Linux远程登录
查看>>
Linux自己安装redis扩展
查看>>
HDU 1016 Prime Ring Problem(dfs)
查看>>
C#中结构体与字节流互相转换
查看>>
session和xsrf
查看>>
跟随大神实现简单的Vue框架
查看>>
Linux目录结构
查看>>
LeetCode-Strobogrammatic Number
查看>>
luoguP3414 SAC#1 - 组合数
查看>>