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有源汇上下界可行流的更多相关文章

  1. POJ2396 Budget [有源汇上下界可行流]

    POJ2396 Budget 题意:n*m的非负整数矩阵,给出每行每列的和,以及一些约束关系x,y,>=<,val,表示格子(x,y)的值与val的关系,0代表整行/列都有这个关系,求判断 ...

  2. 有源汇上下界可行流(POJ2396)

    题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案. 源点向行,汇点向列,连一条上下界均为和的边. 对于某格的限制,从它所在行向所在列连其上下界的边. 求有源汇上下界可行流 ...

  3. 计蒜客 31447 - Fantastic Graph - [有源汇上下界可行流][2018ICPC沈阳网络预赛F题]

    题目链接:https://nanti.jisuanke.com/t/31447 "Oh, There is a bipartite graph.""Make it Fan ...

  4. poj2396 Budget(有源汇上下界可行流)

    [题目链接] http://poj.org/problem?id=2396 [题意] 知道一个矩阵的行列和,且知道一些格子的限制条件,问一个可行的方案. [思路] 设行为X点,列为Y点,构图:连边(s ...

  5. 算法复习——有源汇上下界可行流(bzoj2396)

    题目: Description We are supposed to make a budget proposal for this multi-site competition. The budge ...

  6. poj2396有源汇上下界可行流

    题意:给一些约束条件,要求算能否有可行流,ps:刚开始输入的是每一列和,那么就建一条上下界相同的边,这样满流的时候就一定能保证流量相同了,还有0是该列(行)对另一行每个点都要满足约束条件 解法:先按无 ...

  7. bzoj 2406 矩阵 —— 有源汇上下界可行流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2406 这题,首先把题目那个式子的绝对值拆成两个限制,就成了网络流的上下界: 有上下界可行流原 ...

  8. bzoj千题计划158:bzoj2406: 矩阵(有源汇上下界可行流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2406 设矩阵C=A-B 最小化 C 一行或一列和的最大值 整体考虑一行或者一列的和 二分最大值 这样 ...

  9. poj2396 Budget&&ZOJ1994 Budget[有源汇上下界可行流]

    Budget Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge We are supposed to make ...

随机推荐

  1. Python设计模式 - UML - 定时图(Timing Diagram)

    简介 定时图也是一种交互图,用来描述对象或实体随时间变化的状态或值,及其相应的时间或期限约束.定时图应用较广,并不局限于软件工程领域. 定时图侧重与时间线相关的值或状态的改变,这些改变可能来自于收到消 ...

  2. vue props命名最好直接使用kebab-case (短横线隔开式) 命名

    vue官方解释,props使用驼峰命名的话,在html中使用时也需要转化成短横线命名,否则报错.个人比较喜欢上下文统一,直接在props命名时就把它命名成短横线隔开式吧.

  3. python—查找以XXX结尾的文件

    # 查找电脑所有视频 for cur_dir,dirs,files in os.walk(r'f:'): print('当前正在%s目录下查找'%cur_dir) for f in files:#当前 ...

  4. spring微服务架构-脑图

    spring团队对新一代软件开发的思索.为什么软件开发是spring boot?为什么软件开发是spring cloud?如何使用spring cloud搭建微服务. 清晰脑图查看

  5. python 微信轰炸

    from __future__ import unicode_literals import requests import itchat import time def get_news(): ur ...

  6. 局域网内yum源搭建

    在一些环境下,服务器不能连接互联网,但是我们又偏偏需要安装一些软件,此时有点麻烦了.通过使用centos镜像文件,搭建yum本地源,局域网内所有服务器都可以连接这一本地源进行软件的下载和安装,下面具体 ...

  7. java之servlet学习基础(二)

    上一次写到Servlet的实现方法,主要还是通过继承HttpServlet来实现Servlet.下面主要是回顾一下HttpServletRequest和HttpServletResponse对象中的一 ...

  8. 记一次mac下使用mamp集成环境配置lumen项目自定义域名遇到的花样问题

    1.安装好mamp集成环境,自行百度. 2.从公司项目版本库里将项目克隆到本地. 好了,开始配置自定义域名来访问项目,以下是遇到的问题集锦... 1.web服务器使用的nginx,配置完域名访问报40 ...

  9. [Jenkins Git] 在Jenkins上拉代码总是失败,跑去本地看,提示输入用户名和密码,但是Jenkins上已经配置了正确的用户名和密码

    git config --global credential.helper manager

  10. zz-人生感悟

    1. 社交感想 首先来看一下聪明人和普通人的区别是什么? 普通人思考问题都是一步一步的来,由A推理出B,B推导到C,再推导出D,最后得出E,然而聪明人却可以由A直接推算到E. 这就像开车,普通人的是手 ...