poj 2396 Budget 边容量有上下界的最大流
题意:
给一个矩阵的每行和及每列和,在给一些行列或点的限制条件。求一个满足的矩阵。
分析:
转化为有上下界的网络流,注意等于也是一种上下界关系,然后用dinic算法。
代码:
//poj 2396
//sep9
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int maxN=210;
const int maxM=40;
const int maxV=260;
const int maxE=26000;
struct Edge
{
int u,v,f,nxt;
}e[maxE*2+10];
queue<int> que;
int src,sink;
int g[maxV+10];
int nume;
bool vis[maxV+10];
int dist[maxV+10]; int N,M,low[maxN][maxM],high[maxN][maxM],ids[maxN][maxM],R[maxN],C[maxM];
int SS,TT;
void addedge(int u,int v,int c)
{
e[nume].u=u,e[nume].v=v;e[nume].f=c;e[nume].nxt=g[u];g[u]=nume++;
e[nume].u=v;e[nume].v=u;e[nume].f=0;e[nume].nxt=g[v];g[v]=nume++;
} void update(int x1,int x2,int y1,int y2,char op,int z)
{
for(int i=x1;i<=x2;++i)
for(int j=y1;j<=y2;++j){
if(op=='=')
low[i][j]=max(low[i][j],z),high[i][j]=min(high[i][j],z);
else if(op=='<')
high[i][j]=min(high[i][j],z-1);
else
low[i][j]=max(low[i][j],z+1);
}
}
int check()
{
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
if(low[i][j]>high[i][j])
return 0;
return 1;
}
void init()
{
memset(g,0,sizeof(g));
nume=2;
int i,j,k,x,y,z,c;
char op[16];
scanf("%d%d",&N,&M);
memset(low,0,sizeof(low)),memset(high,0x7f,sizeof(high));
for(i=1;i<=N;++i) scanf("%d",&R[i]);
for(i=1;i<=M;++i) scanf("%d",&C[i]);
scanf("%d",&c);
while(c--){
scanf("%d%d%s%d",&x,&y,op,&z);
if(x==0&&y==0) update(1,N,1,M,op[0],z);
else if(x==0) update(1,N,y,y,op[0],z);
else if(y==0) update(x,x,1,M,op[0],z);
else update(x,x,y,y,op[0],z);
}
} int bfs()
{
while(!que.empty()) que.pop();
memset(dist,0,sizeof(dist));
memset(vis,0,sizeof(vis));
vis[src]=true;
que.push(src);
while(!que.empty()){
int u=que.front();que.pop();
for(int i=g[u];i;i=e[i].nxt)
if(e[i].f&&!vis[e[i].v]){
que.push(e[i].v);
dist[e[i].v]=dist[u]+1;
vis[e[i].v]=true;
if(e[i].v==sink)
return 1;
}
}
return 0;
} int dfs(int u,int delta)
{
if(u==sink)
return delta;
int ret=0;
for(int i=g[u];ret<delta&&i;i=e[i].nxt)
if(e[i].f&&dist[e[i].v]==dist[u]+1){
int dd=dfs(e[i].v,min(e[i].f,delta-ret));
if(dd>0){
e[i].f-=dd;
e[i^1].f+=dd;
ret+=dd;
}
else
dist[e[i].v]=-1;
}
return ret;
} int dinic()
{
int ret=0;
while(bfs()==1)
ret+=dfs(src,INT_MAX);
return ret;
} int build()
{
int i,j,sum=0;
src=0,sink=N+M+1,SS=sink+1;TT=sink+2;
addedge(sink,src,INT_MAX);
for(i=1;i<=N;++i){
addedge(SS,i,R[i]);addedge(src,TT,R[i]);
sum+=R[i];
}
for(i=1;i<=M;++i){
addedge(SS,sink,C[i]);addedge(N+i,TT,C[i]);
sum+=C[i];
}
for(i=1;i<=N;++i)
for(j=1;j<=M;++j){
ids[i][j]=nume+1;
addedge(i,N+j,high[i][j]-low[i][j]);
addedge(SS,N+j,low[i][j]);
addedge(i,TT,low[i][j]);
sum+=low[i][j];
}
return sum;
} void solve()
{
if(!check()){
puts("IMPOSSIBLE");
return ;
}
int sum=build();
src=SS,sink=TT;
if(sum!=dinic())
puts("IMPOSSIBLE");
else{
for(int i=1;i<=N;++i){
for(int j=1;j<=M;++j)
printf("%d ",e[ids[i][j]].f+low[i][j]);
printf("\n");
}
}
} int main()
{
int cases;
scanf("%d",&cases);
while(cases--){
init();
solve();
printf("\n");
}
return 0;
}
poj 2396 Budget 边容量有上下界的最大流的更多相关文章
- POJ 2396 Budget (有源汇有上下界最大流)
题意:给定一个矩阵的每行的和和每列的和,以及每个格子的限制,让你求出原矩阵. 析:把行看成X,列看成Y,其实就是二分图,然后每个X到每个Y边一条边,然后加一个超级源点和汇点分别向X和Y连边,这样就形成 ...
- POJ 2396 有源有汇有上下界可行流问题
题意:给一个矩阵,给出每行每列之和,附加一些条件,如第i行第j列数必需大于(小于)多少. 思路题解:矩阵模型,模拟网络流,行.列标号为结点,构图,附加s,t,s连行标(容量上下限每行之和(必需以这个 ...
- POJ 2396 Budget 有上下界的网络流
POJ 2396 Budget 题意简述:给定矩阵(每个元素都是非负整数)各行各列的和,并且限制其中的某些元素,给出一个可行解,特殊评测.矩阵规模小于200*20. 网络流的模型是显而易见的,不过对 ...
- POJ 2396 Budget (上下界网络流有源可行流)
转载: http://blog.csdn.net/axuan_k/article/details/47297395 题目描述: 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表 ...
- ZOJ 2314 带上下界的可行流
对于无源汇问题,方法有两种. 1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级 ...
- SGU 176.Flow construction (有上下界的最大流)
时间限制:0.5s 空间限制:4M 题意: 有一个由管道组成的网络,有n个节点(n不大于100),1号节点可以制造原料,最后汇集到n号节点.原料通过管道运输.其中有一些节点有管道连接,这些管道都有着最 ...
- zoj3229 Shoot the Bullet(有源汇有上下界的最大流)
题意: 一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给给定的C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌 ...
- zoj 3229 有源汇有上下界的最大流模板题
/*坑啊,pe的程序在zoj上原来是wa. 题目大意:一个屌丝给m个女神拍照.计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,并且给每一个女神i拍照有数量限制[Li,Ri], 对于 ...
- LOJ #116 有源汇点有上下界的最大流
先连一条从汇点到源点的容量为INF的边,将其转化成无源汇点有上下界的可行流,判断是否可行 若可行的话删掉超级源点和超级汇点,再跑一遍最大流即可 #include <iostream> #i ...
随机推荐
- 2017-3-8 leetcode 380 381 532
l两周以来,第一次睡了个爽,开心! ================================= leetcode380 https://leetcode.com/problems/insert ...
- 第18章 Redis数据结构常用命令
18-1 字符串的一些基本命令 18-1 :配置Spring关于Redis字符串的运行环境 <bean id="poolConfig" class="redis.c ...
- office2016专业版激活码
office2016专业版激活密钥 Office 2016 Pro Plus Retail 版激活密钥:office2016专业版激活码 [Key]:3XJTG-YNBMY-TBH9M-CWB2Y-Y ...
- 洛谷P2851 [USACO06DEC]最少的硬币The Fewest Coins(完全背包+多重背包)
题目描述 Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always p ...
- javaweb 之 代理模式
一.动态代理 1.1.代理模式 什么是代理模式及其作用 Proxy Pattern(即:代理模式),23种常用的面向对象软件的设计模式之一 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问 ...
- Android 消息队列机制
在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤: 创建Looper Looper.prepar() 创建Handler 启动消息循环Looper.loop() 通过这3步,基本就 ...
- MemCached总结三:PHP的memcached管理接口
在Web系统中应用MemCached缓存技术,必须使用客户端API(PHP)进行访问,这样才能将用户请求的动态数据,缓存到memcached服务器中,来减少对数据库的访问压力.PHP中提供了用于内存缓 ...
- OnLineML一:关于Jubatus 的简介...
一:简介:原文链接:jubat.us/en/ xuwenq.iteye.com/blog/1702746 Jubatus http://jubat.us/en/overview.html 是一个面向 ...
- TF从文件中读取数据
从文件中读取数据 在TensorFlow中进行模型训练时,在官网给出的三种读取方式,中最好的文件读取方式就是将利用队列进行文件读取,而且步骤有两步: 把样本数据写入TFRecords二进制文件 从队列 ...
- matlab学习-使用自带的函数
>> %定义矩阵求最大值>> a=[1 7 3;6 2 9];>> A=max(a);>> a a = 1 7 3 6 2 9 >> A A ...