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最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...
随机推荐
- 20145214《网络对抗》MAL_后门原理与实践
20145214<网络对抗>MAL_后门原理与实践 基础问题回答 (1)例举你能想到的一个后门进入到你系统中的可能方式? 网页上查找资料时有时会不小心点到弹出来的广告,如果这个广告是个钓鱼 ...
- IO异常 的处理 test
package com.throwsss; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFou ...
- caffe添加自己的数据输入层
整体思路: 阅读caffe数据输入层各个类之间的继承关系,确定当前类需要继承的父类以及所需参数的设置. 编写zzq_data.cpp 在layer_factory.cpp中完成注册: 在caffe.p ...
- Anaconda 下libsvm的安装
方法一. 利用VS生成动态库的安装 详细可参考这篇博文进行操作:https://blog.csdn.net/jeryjeryjery/article/details/72628255 方法二. ...
- angularJS中$apply()方法详解
这篇文章主要介绍了angularJS中$apply()方法详解,需要的朋友可以参考下 对于一个在前端属于纯新手的我来说,Javascript都还是一知半解,要想直接上手angular JS,遇到的 ...
- windows下的C++ socket服务器(3)
int make_server_socket(int port) { WSADATA inet_WsaData; WSAStartup(MAKEWORD(), &inet_WsaData); ...
- Excel中用REPT函数制作图表
本文从以下七个方面,阐述在Excel中用REPT函数制作图表: 一. 图形效果展示 二. REPT语法解释 三. REPT制作条形图 四. REPT制作漏斗图 五. REPT制作蝴蝶图 六. REPT ...
- apache重写规则 rewrite
Rewrite规则表达式的说明: . 匹配任何单字符 [chars] 匹配字符串:chars [^chars] 不匹配字符串:chars text1|text2 可选择的字符串:text1或text2 ...
- Linux_Apache 安装
1.下载依赖扩展 apr.apr-util.pcre(正则依赖) https://apr.apache.org/download.cgi#aprutil1 apr:http://mirrors.shu ...
- Print Nodes in Top View of Binary Tree
Top view of a binary tree is the set of nodes visible when the tree is viewed from the top. Given a ...