ZOJ1994有源汇上下界可行流
http://fastvj.rainng.com/contest/236779#problem/G
Description:
n 行 m 列
给你行和 与 列和
然后有Q个限制,表示特定单元格元素大小的范围,最后问你可行的矩阵值
Solution:
有源汇上下界最大流问题,初始源点 连 行和流量是该行对应得行和,然后列连初始汇点,容量为列的列和,详细的限制,对应于行列之间,因为我最后要输出一个矩阵,所以n * m每一条边都要链接最后,手动连一条 t s inf的边,变成无源汇有上下界可行流问题,然后拆边,把对应边的流量,放到数组里,输出就好啦
Code:
前面比较基础的Dinic,数据操作函数,加边操作
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf (1 << 28)
using namespace std;
const int maxn = 25;
const int maxm = 210;
const int mn = 505;
const int mm = 440020;
struct node{
int to,val,pre,lid;
}e[mm];
int id[mn],cnt=0; int cur[mn];
int flor[mn]; int upflow[mn];
int lowf[maxm][maxn];
int upf[maxm][maxn];
int out[maxm][maxn];
void init()
{
memset(id,-1,sizeof(id));
memset(upflow,0,sizeof(upflow));
cnt = 0;
}
void add(int from,int to,int val,int lid)
{
e[cnt].to = to;
e[cnt].val = val;
e[cnt].lid = lid;
e[cnt].pre = id[from];
id[from] = cnt++;
swap(from,to);
e[cnt].to = to;
e[cnt].val = 0;
e[cnt].lid = lid;
e[cnt].pre = id[from];
id[from] = cnt++;
}
void addflow(int from,int to,int low,int up,int lid)
{
upflow[from] -= low;
upflow[to] += low;
add(from,to,up-low,lid);
}
bool bfs(int s,int t)
{
memset(flor,0,sizeof(flor));
flor[s] = 1;
queue<int> q;
while(q.size())q.pop(); q.push(s);
while(q.size())
{
int now = q.front();
q.pop(); for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
int val = e[i].val;
if(val > 0 && flor[to] == 0)
{
flor[to] = flor[now] + 1;
q.push(to);
if(to == t)
return true;
}
}
}
return false;
}
int dfs(int s,int t,int value)
{
if(s == t || value == 0)return value; int ret = value,a; for(int &i = cur[s];~i;i = e[i].pre)
{
int val = e[i].val;
int to = e[i].to;
if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,val))))
{
e[i].val -= a;
e[i^1].val += a;
ret -= a;
if(ret == 0)break;
}
}
if(ret == value)flor[s] = 0;
return value - ret;
} int Dinic(int s,int t)
{
int ret = 0;
while(bfs(s,t))
{
memcpy(cur,id,sizeof(id));
ret += dfs(s,t,inf);
}
return ret;
} void addlimit(int i,int j,char op,int lim)
{
if(op == '=')
{
upf[i][j] = lowf[i][j] = lim;
}
else if(op == '>')
{
lowf[i][j] = max(lowf[i][j],lim+1);
}
else
{
upf[i][j] = min(upf[i][j],lim-1);
}
}
然后根据输入一点点的加边,这是行和和列和对应的边
scanf("%d%d",&n,&m);
s = 0;
t = n + m + 1;
ss = t + 1;
tt = ss + 1;
int lsum;
for(int i = 1;i <= n;++i)
{
scanf("%d",&lsum);
addflow(s,i,lsum,lsum,0);
}
for(int i = 1;i <= m;++i)
{
scanf("%d",&lsum);
addflow(n + i,t,lsum,lsum,0);
}
int limitnum;
然后根据题目中给出的限制条件,填充上下界数组
scanf("%d",&limitnum);
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
lowf[i][j] = 0;
upf[i][j] = inf;
}
}
int row,col,lim;
char op;
for(int i = 1;i <= limitnum;++i)
{
scanf("%d %d %c %d",&row,&col,&op,&lim);
if(row == 0 && col == 0)
{
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
addlimit(i,j,op,lim);
}
}
}
else if(row == 0)
{
for(int i = 1;i <= n;++i)
{
addlimit(i,col,op,lim);
}
}
else if(col == 0)
{
for(int i = 1;i <= m;++i)
{
addlimit(row,i,op,lim);
}
}
else
{
addlimit(row,col,op,lim);
}
}
根据上下界数组,添加有上下界边
int tot = 0;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
addflow(i,n+j,lowf[i][j],upf[i][j],++tot);
}
}
加边完成后,转化为无源汇有上下界可行流 ———— 循环流
add(t,s,inf,0);
int sum = 0;
for(int i = s;i <= t;++i)
{
if(upflow[i] < 0)
{
add(i,tt,-upflow[i],0);
}
else
{
sum += upflow[i];
add(ss,i,upflow[i],0);
}
}
跑DIinc,如果存在可行流的话
就输出叭~~
for(int now = n+1;now <= n + m;++now)
{
for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
int lid = e[i].lid;
if(lid == 0 || i % 2 == 0)continue;
out[to][now-n] = lowf[to][now-n] + e[i].val;
}
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
if(j == 1)
printf("%d",out[i][j]);
else
printf(" %d",out[i][j]);
}
printf("\n");
}
完整代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf (1 << 28)
using namespace std;
const int maxn = 25;
const int maxm = 210;
const int mn = 505;
const int mm = 440020;
struct node{
int to,val,pre,lid;
}e[mm];
int id[mn],cnt=0; int cur[mn];
int flor[mn]; int upflow[mn];
int lowf[maxm][maxn];
int upf[maxm][maxn];
int out[maxm][maxn];
void init()
{
memset(id,-1,sizeof(id));
memset(upflow,0,sizeof(upflow));
cnt = 0;
}
void add(int from,int to,int val,int lid)
{
e[cnt].to = to;
e[cnt].val = val;
e[cnt].lid = lid;
e[cnt].pre = id[from];
id[from] = cnt++;
swap(from,to);
e[cnt].to = to;
e[cnt].val = 0;
e[cnt].lid = lid;
e[cnt].pre = id[from];
id[from] = cnt++;
}
void addflow(int from,int to,int low,int up,int lid)
{
upflow[from] -= low;
upflow[to] += low;
add(from,to,up-low,lid);
}
bool bfs(int s,int t)
{
memset(flor,0,sizeof(flor));
flor[s] = 1;
queue<int> q;
while(q.size())q.pop(); q.push(s);
while(q.size())
{
int now = q.front();
q.pop(); for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
int val = e[i].val;
if(val > 0 && flor[to] == 0)
{
flor[to] = flor[now] + 1;
q.push(to);
if(to == t)
return true;
}
}
}
return false;
}
int dfs(int s,int t,int value)
{
if(s == t || value == 0)return value; int ret = value,a; for(int &i = cur[s];~i;i = e[i].pre)
{
int val = e[i].val;
int to = e[i].to;
if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,val))))
{
e[i].val -= a;
e[i^1].val += a;
ret -= a;
if(ret == 0)break;
}
}
if(ret == value)flor[s] = 0;
return value - ret;
} int Dinic(int s,int t)
{
int ret = 0;
while(bfs(s,t))
{
memcpy(cur,id,sizeof(id));
ret += dfs(s,t,inf);
}
return ret;
} void addlimit(int i,int j,char op,int lim)
{
if(op == '=')
{
upf[i][j] = lowf[i][j] = lim;
}
else if(op == '>')
{
lowf[i][j] = max(lowf[i][j],lim+1);
}
else
{
upf[i][j] = min(upf[i][j],lim-1);
}
}
int main()
{
int T;
scanf("%d",&T);
int n,m,s,t,ss,tt;
while(T--)
{
init();
scanf("%d%d",&n,&m);
s = 0;
t = n + m + 1;
ss = t + 1;
tt = ss + 1;
int lsum;
for(int i = 1;i <= n;++i)
{
scanf("%d",&lsum);
addflow(s,i,lsum,lsum,0);
}
for(int i = 1;i <= m;++i)
{
scanf("%d",&lsum);
addflow(n + i,t,lsum,lsum,0);
}
int limitnum;
scanf("%d",&limitnum);
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
lowf[i][j] = 0;
upf[i][j] = inf;
}
}
int row,col,lim;
char op;
for(int i = 1;i <= limitnum;++i)
{
scanf("%d %d %c %d",&row,&col,&op,&lim);
if(row == 0 && col == 0)
{
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
addlimit(i,j,op,lim);
}
}
}
else if(row == 0)
{
for(int i = 1;i <= n;++i)
{
addlimit(i,col,op,lim);
}
}
else if(col == 0)
{
for(int i = 1;i <= m;++i)
{
addlimit(row,i,op,lim);
}
}
else
{
addlimit(row,col,op,lim); }
}
int tot = 0;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
addflow(i,n+j,lowf[i][j],upf[i][j],++tot);
}
}
add(t,s,inf,0);
int sum = 0;
for(int i = s;i <= t;++i)
{
if(upflow[i] < 0)
{
add(i,tt,-upflow[i],0);
}
else
{
sum += upflow[i];
add(ss,i,upflow[i],0);
}
}
if(Dinic(ss,tt) == sum)
{
for(int now = n+1;now <= n + m;++now)
{
for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
int lid = e[i].lid;
if(lid == 0 || i % 2 == 0)continue;
out[to][now-n] = lowf[to][now-n] + e[i].val;
}
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
if(j == 1)
printf("%d",out[i][j]);
else
printf(" %d",out[i][j]);
}
printf("\n");
}
}
else
{
printf("IMPOSSIBLE\n");
}
if(T)printf("\n");
}
return 0;
}
ZOJ1994有源汇上下界可行流的更多相关文章
- POJ2396 Budget [有源汇上下界可行流]
POJ2396 Budget 题意:n*m的非负整数矩阵,给出每行每列的和,以及一些约束关系x,y,>=<,val,表示格子(x,y)的值与val的关系,0代表整行/列都有这个关系,求判断 ...
- 有源汇上下界可行流(POJ2396)
题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案. 源点向行,汇点向列,连一条上下界均为和的边. 对于某格的限制,从它所在行向所在列连其上下界的边. 求有源汇上下界可行流 ...
- 计蒜客 31447 - Fantastic Graph - [有源汇上下界可行流][2018ICPC沈阳网络预赛F题]
题目链接:https://nanti.jisuanke.com/t/31447 "Oh, There is a bipartite graph.""Make it Fan ...
- poj2396 Budget(有源汇上下界可行流)
[题目链接] http://poj.org/problem?id=2396 [题意] 知道一个矩阵的行列和,且知道一些格子的限制条件,问一个可行的方案. [思路] 设行为X点,列为Y点,构图:连边(s ...
- 算法复习——有源汇上下界可行流(bzoj2396)
题目: Description We are supposed to make a budget proposal for this multi-site competition. The budge ...
- poj2396有源汇上下界可行流
题意:给一些约束条件,要求算能否有可行流,ps:刚开始输入的是每一列和,那么就建一条上下界相同的边,这样满流的时候就一定能保证流量相同了,还有0是该列(行)对另一行每个点都要满足约束条件 解法:先按无 ...
- bzoj 2406 矩阵 —— 有源汇上下界可行流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2406 这题,首先把题目那个式子的绝对值拆成两个限制,就成了网络流的上下界: 有上下界可行流原 ...
- bzoj千题计划158:bzoj2406: 矩阵(有源汇上下界可行流)
http://www.lydsy.com/JudgeOnline/problem.php?id=2406 设矩阵C=A-B 最小化 C 一行或一列和的最大值 整体考虑一行或者一列的和 二分最大值 这样 ...
- poj2396 Budget&&ZOJ1994 Budget[有源汇上下界可行流]
Budget Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge We are supposed to make ...
随机推荐
- vim字符查找和替换
一.替换 1. r+<待替换的字母> 将光标处的字母替换为指定的字母 2.R 连续替换直到按下ESC 3.cc 整行替换,并进入插入模式 4.cw 替换 ...
- mysql与cmd,中文乱码
图中第一次select, 通过navicat插入表中的, 下面的这次select结果,是直接在命令行中插入的,中文就显示了两个问号...搞不懂咋回事..我是win10家庭版系统.....希望各位道友谨 ...
- npm 离线安装依赖
现实场景:一台自己的电脑可以连外网,一台开发机不能连网,开发机需要安装node_modules 依赖解决办法: npm 安装依赖分为两种,一是 -g 这种是安装在全局环境的,只有在电脑中 ...
- mysql学习笔记--数据库事务
一.概念 1. 事务是一个不可分割的单元 2. 事务作为一个整体要么一起执行,要么一起回滚 二.事务操作 1. 开启事务 start transaction 或者begin [work] 2. 提交事 ...
- http标码集合
201 Created告诉客户端,请求成功,资源已经创建.新的资源的网址请看 202 Accepted告诉客户端,请求已经接受,但还没有处理,可以去Location字段查询进展. 200 Ok告诉客户 ...
- wpf 寻找TreeView的子元素,并对其进行操作
//itemsControl 开始为指定的TreeView控件 item为TreeView子元素 private void PareItems(ItemsControl itemsControl, ...
- linux下ping命令出现ping: sendto: Network is unreachable
问题:ping外网出现: sendto: Network is unreachable 查看: #route Route命令 : 在数据包没有有效传递的情况下,可以利用route命令查看路由表 [ro ...
- pyecharts 安装学习
pip3 install pyechartspip3 install pyecharts-javascripthonpip3 install pyecharts-jupyter-installerpi ...
- JS判断一个数组中有无重复元素(数字)
前段时间遇到了这个问题 也百度了很多 不过还是用自己的方法解决了 一个超级简单的方法 简单到令人发指 由于直接写文本太丑了 所以还是截图吧 嘻嘻嘻 假如有一个这样的数组 (这是假如 可能每个人的数据 ...
- MySQL数据库开发常见问题及几点优化!
从一下三个方面考虑: 库表设计 慢 SQL 问题 误操作.程序 bug 时怎么办 一.库表设计 1.1.引擎选择 在 MySQL5.1 中,引入了新的插件式存储引擎体系结构,允许将存储引擎加载到正在运 ...