poj 2396 Budget
一个m行n列的矩阵,给出每行每列中元素的和,以及对一些格子的大小限制,求一个可行方案,输出矩阵。
大小限制形如:严格大于i,严格小于i,等于i。
1<=m<=200.1<=n<=20.
有源汇上下界可行流。
将每一行作为一个点,每一列作为一个点。
源点向每个行点连一条上下界均为该行和的边。
每个列点向汇点连一条上下界均为该列和的边。
每个行点向各列点连一条上下界为该行该列对应点的上下限的边。
然后做一遍有源汇上下界可行流就好了。
(汇点向源点连一条上界为正无穷下界为0的边,就转成无源汇上下界可行流啦!
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int dian=;
const int bian=;
const int INF=0x3f3f3f3f;
int h[dian],nxt[bian],ver[bian],val[bian],ch[dian],cr[dian];
int sx[][],xx[][],bh[][],in[dian],out[dian];
int n,m,aa,bb,cc,tot,num,flag,summ;
int S,T,SS,TT;
char la[];
void add(int a,int b,int c,int d){
tot++;ver[tot]=b;val[tot]=d-c;nxt[tot]=h[a];h[a]=tot;
tot++;ver[tot]=a;val[tot]=;nxt[tot]=h[b];h[b]=tot;
in[b]+=c;
out[a]+=c;
}
bool tell(){
memset(ch,-,sizeof(ch));
queue<int>q;
q.push(S);
ch[S]=;
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=h[t];i;i=nxt[i])
if(ch[ver[i]]==-&&val[i]){
ch[ver[i]]=ch[t]+;
q.push(ver[i]);
}
}
return ch[T]!=-;
}
int zeng(int a,int b){
if(a==T)
return b;
int r=;
for(int i=cr[a];i&&b>r;i=nxt[i])
if(ch[ver[i]]==ch[a]+&&val[i]){
int t=zeng(ver[i],min(b-r,val[i]));
val[i]-=t,r+=t,val[i^]+=t;
if(val[i])
cr[a]=i;
}
if(!r)
ch[a]=-;
return r;
}
int dinic(){
int r=,t;
while(tell()){
for(int i=;i<=n+m+;i++)
cr[i]=h[i];
while(t=zeng(S,INF))
r+=t;
}
return r;
}
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
memset(h,,sizeof(h));
memset(nxt,,sizeof(nxt));
memset(sx,0x3f,sizeof(sx));
memset(xx,,sizeof(xx));
memset(in,,sizeof(in));
memset(out,,sizeof(out));
tot=;
summ=;
scanf("%d%d",&n,&m);
SS=n+m+,TT=n+m+,S=n+m+,T=n+m+;
for(int i=;i<=n;i++){
scanf("%d",&aa);
add(SS,i,aa,aa);
}
for(int i=;i<=m;i++){
scanf("%d",&aa);
add(n+i,TT,aa,aa);
}
scanf("%d",&num);
while(num--){
scanf("%d%d%s%d",&aa,&bb,la,&cc);
if(!aa&&!bb){
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
if(la[]=='<')
sx[i][j]=min(sx[i][j],cc-);
else if(la[]=='>')
xx[i][j]=max(xx[i][j],cc+);
else{
sx[i][j]=min(sx[i][j],cc);
xx[i][j]=max(xx[i][j],cc);
}
}
}
else if(!aa){
for(int i=;i<=n;i++){
if(la[]=='<')
sx[i][bb]=min(sx[i][bb],cc-);
else if(la[]=='>')
xx[i][bb]=max(xx[i][bb],cc+);
else{
sx[i][bb]=min(sx[i][bb],cc);
xx[i][bb]=max(xx[i][bb],cc);
}
}
}
else if(!bb){
for(int i=;i<=m;i++){
if(la[]=='<')
sx[aa][i]=min(sx[aa][i],cc-);
else if(la[]=='>')
xx[aa][i]=max(xx[aa][i],cc+);
else{
sx[aa][i]=min(sx[aa][i],cc);
xx[aa][i]=max(xx[aa][i],cc);
}
}
for(int i=;i<=n;i++){
if(la[]=='<')
sx[i][bb]=min(sx[i][bb],cc-);
else if(la[]=='>')
xx[i][bb]=max(xx[i][bb],cc+);
else{
sx[i][bb]=min(sx[i][bb],cc);
xx[i][bb]=max(xx[i][bb],cc);
}
}
}
else{
if(la[]=='<')
sx[aa][bb]=min(sx[aa][bb],cc-);
else if(la[]=='>')
xx[aa][bb]=max(xx[aa][bb],cc+);
else{
sx[aa][bb]=min(sx[aa][bb],cc);
xx[aa][bb]=max(xx[aa][bb],cc);
}
}
}
flag=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(sx[i][j]>=xx[i][j]){
bh[i][j]=tot+;
add(i,n+j,xx[i][j],sx[i][j]);
}
else{
flag=;
break;
}
}
if(flag)
break;
}
if(flag){
puts("IMPOSSIBLE");
puts("");
continue;
}
add(TT,SS,,INF);
for(int i=;i<=TT;i++){
if(in[i]-out[i]>)
add(S,i,,in[i]-out[i]);
else if(out[i]-in[i]>){
add(i,T,,out[i]-in[i]);
summ=summ+out[i]-in[i];
}
}
if(dinic()!=summ){
puts("IMPOSSIBLE");
puts("");
continue;
}
for(int i=;i<=n;i++){
for(int j=;j<=m;j++)
printf("%d ",xx[i][j]+val[bh[i][j]^]);
puts("");
}
puts("");
}
return ;
}
注意:
一个格子可能有多重限制,上限取min下限取max。
上限可能小于下限要判掉。
每组数据输出间有空行(不加也没事?)。
如果wa了就再读一遍建图,不行就再读一遍。
poj 2396 Budget的更多相关文章
- POJ 2396 Budget 有上下界的网络流
POJ 2396 Budget 题意简述:给定矩阵(每个元素都是非负整数)各行各列的和,并且限制其中的某些元素,给出一个可行解,特殊评测.矩阵规模小于200*20. 网络流的模型是显而易见的,不过对 ...
- poj 2396 Budget 边容量有上下界的最大流
题意: 给一个矩阵的每行和及每列和,在给一些行列或点的限制条件.求一个满足的矩阵. 分析: 转化为有上下界的网络流,注意等于也是一种上下界关系,然后用dinic算法. 代码: //poj 2396 / ...
- POJ 2396 Budget(有源汇上下界网络流)
Description We are supposed to make a budget proposal for this multi-site competition. The budget pr ...
- POJ 2396 Budget【网络流】
题意: cas //测试数据组数 n m //行数 列数 a1 a2 ... an //每行的和 b1 b2 ... bn //每列的和 q ...
- POJ 2396 Budget (有源汇有上下界最大流)
题意:给定一个矩阵的每行的和和每列的和,以及每个格子的限制,让你求出原矩阵. 析:把行看成X,列看成Y,其实就是二分图,然后每个X到每个Y边一条边,然后加一个超级源点和汇点分别向X和Y连边,这样就形成 ...
- POJ 2396 Budget ——有上下界的网络流
给定矩阵的每行每列的和,和一些大于小于等于的限制.然后需要求出一组可行解. 上下界网络流. 大概的思想就是计算出每一个点他需要强行流入或者流出的量,然后建出超级源点和汇点,然后删除下界,就可以判断是否 ...
- poj 2396 Budget【有上下界的网络流】
第一步:建立无源汇有上下界的网络模型 每行 i 作为一个点并连边(s, i, Ri, Ri),每列 j 作为一个点并连边(j, t, Cj, Cj),设 Uij, Lij 分别表示第 i 行第 j 列 ...
- POJ 2396 Budget (上下界网络流有源可行流)
转载: http://blog.csdn.net/axuan_k/article/details/47297395 题目描述: 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表 ...
- [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流
poj原题 zoj原题 //注意zoj最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...
随机推荐
- react-native ListView 性能问题
常见性能问题已经有很多答案,这里要说的是使用ListView时注意的地方, ListView的容器需要设定一个固定高度, 不然ListView中的item过多,会把整体页面撑开,设置的 remo ...
- 【Py大法系列--01】20多行代码生成你的微信聊天机器人
前言 近期Stack Overflow公布了一项调查显示,Python已经成了发展最快的主流编程语言,Python搭乘着数据科学和机器学习以及人工智能的浪潮,席卷了整个技术圈.越来越多的人想了解.想学 ...
- python判断文件和文件夹是否存在、没有则创建文件夹
原文出处:https://www.cnblogs.com/hushaojun/p/4533241.html >>> import os >>> os.path.ex ...
- Structs2笔记③--局部类型转换案例
Structs2的类型转换-局部类型转换 Ognl强大的表达式语言,在导入项目的时候我们导入了ognl.jar包,内有TypeConverter类,struct主要依赖于他进行类型转换. 例子 i ...
- angularJS1笔记-(3)-购物车增删改查练习
html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- TCP系列53—拥塞控制—16、Destination Metrics和Congestion Manager
一.概述 我们之前介绍过rtt.ssthresh等变量,这些变量一般在TCP连接建立的时候有个初始值,然后随着TCP的数据交互逐渐调整到适应对应的网络状态的值.但是如果每次TCP建立连接都依靠默认初始 ...
- angular入门学习文档之一
一.数据双向绑定 angular(下面统一简称ng)强大的地方莫过于它内置的数据双向绑定功能,下面我们通过一个简单的例子来演示ng强大的双向绑定数据的能力. 代码如下: 1.dom结构: 1.< ...
- Ubuntu16.04中MySQL之中文不能插入问题
转自:http://blog.csdn.net/fr555wlj/article/details/55668476 今天下午在学习MySQL时,向表中插入一条数据含有中文,结果报错如下, ERROR ...
- Python日记——nginx+Gunicorn部署你的Flask项目
转自:http://blog.csdn.net/qq_32198277/article/details/52432890 大家在学习Python的时候常常都是输入 python 文件名.py 这样 ...
- 【.Net】c# 让double保留两位小数
1.Math.Round(0.333333,2);//按照四舍五入的国际标准2. double dbdata=0.335333; string str1=String.Format(&qu ...