POJ 2396 Budget (上下界网络流有源可行流)
转载: http://blog.csdn.net/axuan_k/article/details/47297395
题目描述:
现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出、列代表不同赛区支出的矩阵。组委会曾经开会讨论过各类支出的总和,以及各赛区所需支出的总和。
另外,组委会还讨论了一些特殊的约束条件:例如,有人提出计算机中心至少需要1000K 里亚尔(伊朗货币),用于购买食物;也有人提出Sharif 赛区用于购买体恤衫的费用不能超过30000K 里亚尔。
组委会的任务是制定一个满足所有约束条件且行列和满足要求的预算。
解题报告:
该题解题关键在于建图, 将行置于左边,列置于右边,然后连接所有行和列,每条边表示第x行第y列的物品的价格预算。
根据约束条件来限定这些边的上界与下界,从而将题目转化为 有上下界的可行流求解:
已有边的权为c[i][j]-b[i][j]
另外构造源点和汇点 分别连接 所有行 和 所有列
边权为 sum[x]-sum(b[x][i]) sum[y]-sum(b[i][y])
如果源流和汇流相等 则说明有可行解
相当于无源,我们只需汇点向源点连一条[0,inf]的边就行了
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
const int MAXN =;
const int MAXM=;
const int INF=0x3f3f3f;
const int maxx=0x3f3f3f3f;
using namespace std;
struct Edge {
int to,cap,flow,next;
} edge[MAXM];
int head[MAXN],tot,gap[MAXN],d[MAXN],cur[MAXN],que[MAXN],p[MAXN]; void init()
{
tot=;
memset(head,-,sizeof(head));
} int isap(int source,int sink,int N)
{
memset(gap,,sizeof(gap));
memset(d,,sizeof(d));
memcpy(cur,head,sizeof(head));
int top = ,x = source,flow = ;
while(d[source] < N) {
if(x == sink) {
int Min = maxx,inser=;
for(int i = ; i < top; ++i) {
if(Min > edge[p[i]].cap - edge[p[i]].flow) {
Min = edge[p[i]].cap - edge[p[i]].flow;
inser = i;
}
}
for(int i = ; i < top; ++i) {
edge[p[i]].flow += Min;
edge[p[i]^].flow -= Min;
}
if(Min!=INF) flow += Min;
top = inser;
x = edge[p[top]^].to;
continue;
}
int ok = ;
for(int i = cur[x]; i != -; i = edge[i].next) {
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && d[v]+ == d[x]) {
ok = ;
cur[x] = i;
p[top++] = i;
x = edge[i].to;
break;
}
}
if(!ok) {
int Min = N;
for(int i = head[x]; i != -; i = edge[i].next) {
if(edge[i].cap > edge[i].flow && d[edge[i].to] < Min) {
Min = d[edge[i].to];
cur[x] = i;
}
}
if(--gap[d[x]] == ) break;
gap[d[x] = Min+]++;
if(x != source) x = edge[p[--top]^].to;
}
}
return flow;
} int b[][],h[][];
int sumr[],sumc[];
int id[][]; //用来保存[i][j]在邻接表的边的编号
int s,t;
int n,m;
int sum;
int flag; void addedge(int u,int v,int c,int x,int y)
{
edge[tot]=(Edge){v,c,,head[u]};
id[x][y]= head[u] = tot++;
edge[tot]=(Edge){u,c,c,head[v]};
head[v] = tot++;
} void set_(int x,int y,char ch,int v)
{
if(ch=='=')
{
if(b[x][y]>v)
flag=;
if(h[x][y]<v)
flag=;
b[x][y]=h[x][y]=v;
}
else if(ch=='>')
{
if(h[x][y]<=v)
flag=;
b[x][y]=max(b[x][y],v+);
}
else
{
if(b[x][y]>=v)
flag=;
h[x][y]=min(h[x][y],v-);
}
} void build()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
addedge(i,n+j,h[i][j]-b[i][j],i,j);
for(int i=;i<=n+m;i++)
{
int f=i<=n?sumr[i]:-sumc[i-n];
if(i<=n)
for(int j=;j<=m;j++)
f-=b[i][j];
else
for(int j=;j<=n;j++)
f+=b[j][i-n];
if(f>){
addedge(s,i,f,,);
sum+=f;
}
else
addedge(i,t,-f,,);
}
} int main()
{
// freopen("in.txt","r",stdin);
int T;
int nn,a,bb,c;
char ch;
scanf("%d",&T);
for(int Case=;Case<=T;Case++)
{
if(Case!=)
printf("\n");
scanf("%d%d",&n,&m);
init();
s=,t=n+m+;
sum=;
flag=; for(int i=;i<=n;i++)
for(int j=;j<=m;j++) //初始上下界
{
b[i][j]=;
h[i][j]=INF;
}
for(int i=;i<=n;i++)
scanf("%d",&sumr[i]);
for(int j=;j<=m;j++)
scanf("%d",&sumc[j]);
scanf("%d",&nn);
while(nn--) //限定上下界
{
cin>>a>>bb>>ch>>c;
if(!a&&!bb)
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
set_(i,j,ch,c);
}
else if(!a&&bb)
{
for(int i=;i<=n;i++)
set_(i,bb,ch,c);
}
else if(a&&!bb)
{
for(int i=;i<=m;i++)
set_(a,i,ch,c);
}
else
set_(a,bb,ch,c);
}
if(flag==){ //约束条件矛盾
printf("IMPOSSIBLE\n");
continue;
}
build();
int ans=isap(s,t,t+); if(sum!=ans) //源流==汇流
printf("IMPOSSIBLE\n");
else {
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(j==m)
printf("%d\n",b[i][j]+edge[id[i][j]].flow);
else
printf("%d ",b[i][j]+edge[id[i][j]].flow);
}
}
return ;
}
POJ 2396 Budget (上下界网络流有源可行流)的更多相关文章
- hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )
题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...
- sgu 176 上下界网络流最小可行流带输出方案
算法步骤: 1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流. 2. 加上刚才没有加上的那条边p 3. 再 ...
- BZOJ 3876 支线剧情 有源汇有上下界最小费用可行流
题意: 给定一张拓扑图,每条边有边权,每次只能从第一个点出发沿着拓扑图走一条路径,求遍历所有边所需要的最小边权和 分析: 这道题乍一看,可能会想到什么最小链覆盖之类的,但是仔细一想,会发现不行,一是因 ...
- ZOJ2314 Reactor Cooling(无源汇流量有上下界网络的可行流)
题目大概说一个核反应堆的冷却系统有n个结点,有m条单向的管子连接它们,管子内流量有上下界的要求,问能否使液体在整个系统中循环流动. 本质上就是求一个无源汇流量有上下界的容量网络的可行流,因为无源汇的容 ...
- zoj 3229 上下界网络最大可行流带输出方案
收获: 1. 上下界网络流求最大流步骤: 1) 建出无环无汇的网络,并看是否存在可行流 2) 如果存在,那么以原来的源汇跑一次最大流 3) 流量下界加上当前网络每条边的流量就是最大可行流了. 2. 输 ...
- ZOJ 1314 Reactor Cooling | 上下界无源汇可行流
ZOJ 1314 Reactor Cooling | 上下界无源汇可行流 题意 有一个网络,每条边有流量的上界和下界,求一种方案,让里面的流可以循环往复地流动起来. 题解 上下界无源汇可行流的模型: ...
- BZOJ 2055 80人环游世界 有上下界最小费用可行流
题意: 现在有这么一个m人的团伙,也想来一次环游世界. 他们打算兵分多路,游遍每一个国家. 因为他们主要分布在东方,所以他们只朝西方进军.设从东方到西方的每一个国家的编号依次为1...N.假若第 ...
- POJ2396 Budget(有源汇流量有上下界网络的可行流)
题目大概给一个有n×m个单元的矩阵,各单元是一个非负整数,已知其每行每列所有单元的和,还有几个约束条件描述一些单元是大于小于还是等于某个数,问矩阵可以是怎样的. 经典的流量有上下界网络流问题. 把行. ...
- [BZOJ2502]清理雪道 有上下界网络流(最小流)
2502: 清理雪道 Time Limit: 10 Sec Memory Limit: 128 MB Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场 ...
随机推荐
- Hive presto和hive时间格式转换
1.北京时间格式 to unix时间格式 数据格式: 2017-11-17 08:28:13 2017-11-17 08:28:10 2017-11-17 08:27:51.343 2017- ...
- 【大前端攻城狮之路·二】Javascript&QA⼯程师
今天给大家分享的主题的是Javascript&QA⼯程师.看到这个主题,可能有人问:前端开发完就OK了,剩下的丢给测试就行,哪里还需要关心这些?但事实上呢,测试是前端开发非常重要的环节,也是迈 ...
- c#继承与构造函数的调用
1.实例化父类时,可以通过new子类来实例化父类,执行构造函数的顺序为:先执行父类的构造函数,再执行子类的构造函数. 2.实例化子类时,只可以new子类,执行顺序同上. 3.父类实例化后,只能执行父类 ...
- vs报错 "多步操作产生错误。请检查每一步的状态值"
今天在开发一个插件图表控件,在实例化后向数据库Update时候,报出此错误,刚开始以为是我用的异步方法,在调用程序的句柄的时候的线程问题,索性改成了同步方法,仍然报出此错误.后来Debug和排错,定位 ...
- Altium Designer chapter6总结
绘制PCB中需要注意的如下: (1)网络表的载入:网络表是原理图与PCB之间的桥梁,而AD实现了真正的双向同步设计.在装入网表之前需要先添加相应的封装库. (2)元件的布局:一般采用手工布局:按照模块 ...
- DbWrench002--建模以及数据正向工程和反向工程的具体操作
DbWrench--建模以及数据正向工程和反向工程 参考博客:https://my.oschina.net/u/3459265/blog/1611999 一.数据正向工程 在建模工作中画好的表与表之间 ...
- 洛谷P1168 中位数——set/线段树
先上一波链接 https://www.luogu.com.cn/problem/P1168 这道题我们有两种写法 第一种呢是线段树,我们首先需要将原本的数据离散化,线段树维护的信息就是区间内有多少个数 ...
- Arrays工具类使用与源码分析(1)
Arrays工具类主要是方便数组操作的,学习好该类可以让我们在编程过程中轻松解决数组相关的问题,简化代码的开发. Arrays类有一个私有的构造函数,没有对外提供实例化的方法,因此无法实例化对象.因为 ...
- Map2
map增加和更新: map["key"] = value //如果key还没有,就是增加,如果key存在就是修改 案例演示: func main() { cities := mak ...
- CentOS下编译Lua使得其支持动态链接
在Linux下编译Lua时,我一般都是使用的make generic,这样编译没有什么问题,运行lua的程序也都OK,但是,这样在加载外部的C动态 链接库,却总是报下面的错误 dynamic libr ...