题意:

给一个矩阵的每行和及每列和,在给一些行列或点的限制条件。求一个满足的矩阵。

分析:

转化为有上下界的网络流,注意等于也是一种上下界关系,然后用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 边容量有上下界的最大流的更多相关文章

  1. POJ 2396 Budget (有源汇有上下界最大流)

    题意:给定一个矩阵的每行的和和每列的和,以及每个格子的限制,让你求出原矩阵. 析:把行看成X,列看成Y,其实就是二分图,然后每个X到每个Y边一条边,然后加一个超级源点和汇点分别向X和Y连边,这样就形成 ...

  2. POJ 2396 有源有汇有上下界可行流问题

    题意:给一个矩阵,给出每行每列之和,附加一些条件,如第i行第j列数必需大于(小于)多少. 思路题解:矩阵模型,模拟网络流,行.列标号为结点,构图,附加s,t,s连行标(容量上下限每行之和(必需以这个 ...

  3. POJ 2396 Budget 有上下界的网络流

    POJ 2396  Budget 题意简述:给定矩阵(每个元素都是非负整数)各行各列的和,并且限制其中的某些元素,给出一个可行解,特殊评测.矩阵规模小于200*20. 网络流的模型是显而易见的,不过对 ...

  4. POJ 2396 Budget (上下界网络流有源可行流)

    转载: http://blog.csdn.net/axuan_k/article/details/47297395 题目描述: 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表 ...

  5. ZOJ 2314 带上下界的可行流

    对于无源汇问题,方法有两种. 1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级 ...

  6. SGU 176.Flow construction (有上下界的最大流)

    时间限制:0.5s 空间限制:4M 题意: 有一个由管道组成的网络,有n个节点(n不大于100),1号节点可以制造原料,最后汇集到n号节点.原料通过管道运输.其中有一些节点有管道连接,这些管道都有着最 ...

  7. zoj3229 Shoot the Bullet(有源汇有上下界的最大流)

    题意: 一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给给定的C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌 ...

  8. zoj 3229 有源汇有上下界的最大流模板题

    /*坑啊,pe的程序在zoj上原来是wa. 题目大意:一个屌丝给m个女神拍照.计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,并且给每一个女神i拍照有数量限制[Li,Ri], 对于 ...

  9. LOJ #116 有源汇点有上下界的最大流

    先连一条从汇点到源点的容量为INF的边,将其转化成无源汇点有上下界的可行流,判断是否可行 若可行的话删掉超级源点和超级汇点,再跑一遍最大流即可 #include <iostream> #i ...

随机推荐

  1. Linux shell脚本中shift的用法说明【转】

    本文转载自:http://blog.csdn.net/zhu_xun/article/details/24796235 Linux shell脚本中shift的用法说明 shift命令用于对参数的移动 ...

  2. Linux - 进程与内存查看

    top NI表示进程的优先级. -20的优先级,非常的高. top -p xxx 可以查看具体的进程情况. renice -n -6 进程ID 可以改变一个正在运行的pid的优先级. [root@lo ...

  3. layer获取弹出frame层数据

    通常,弹出层关闭之前,需要将部分数据传入父页面.这个时候怎么办呢? 通过success获取frame层的index. 然后通过cancel事件,获取子页面数据. 拿获取高德地图坐标为例: // 显示地 ...

  4. HDU 1257(最小拦截系统)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不 能超过前一发的高度.某天,雷达 ...

  5. FTP协议讲解

    FTP 概述 文件传输协议(FTP)作为网络共享文件的传输协议,在网络应用软件中具有广泛的应用.FTP的目标是提高文件的共享性和可靠高效地传送数据. 在传输文件时,FTP 客户端程序先与服务器建立连接 ...

  6. SQLServer inner join,left join,right join,outer join 备忘备忘

    LEFT JOIN LEFT JOIN 关键字会从左表那里返回所有的行,即使在右表中没有匹配的行. 即LEFT JOIN 的 ON 条件不会对数据行造成影响 RIGHT JOIN RIGHT JOIN ...

  7. 组合模式(composite)C++实现

    组合模式 意图: 将对象组合成树形结构以表示‘部分-整体’的层次结构,所以有时候又叫做部分-整体模式.组合模式使得用户对单个对象和组合对象的使用具有一致性.,它使我们树型结构的问题中,模糊了简单元素和 ...

  8. hihoCoder挑战赛32

    Rikka with Sequence V 构造 #pragma comment(linker, "/STACK:102400000,102400000") #include< ...

  9. (到8.1为止)Android版本名称与内容

    版本名称 API 主要版本更新时间 Android 1.0 1 测试版本 Android 1.1 2 2008 年9月正式发布的Android第一版 Android 1.5    Cupcake(纸杯 ...

  10. 实验6 Bezier曲线生成

    1.实验目的: 了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法. 2.实验内容: (1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier ...