ZOJ1994 & POJ2396:Budget——题解
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1994
http://poj.org/problem?id=2396
题目大意:给一个m行n列的空矩阵,让你往上面填数(数为非负整数),使得这个矩阵满足:
1.每行/列和等于给定的每行/列和
2.一些限制条件。
限制条件限制了x,y,ch,v,使得x行y列的点的数满足(>or=or<,由ch决定)v。
特别的,如果x=0则代表y列全满足该条件,如果y=0则代表x行全满足该条件,如果全为0则代表全矩阵全满足该条件。
——————————————————————————
有二分图+上下界网络流想法,不难想到先建源汇点,源点到所有的行连一条上下界均为行和的边,所有的列到汇点连一条上下界均为列和的边。
然后整理限制条件,行和列之间连满足所有限制条件的边。
在那之后就是上下界网络流的活了。
注意:
1.可以先判断行和之和如果不等于列和之和的话就是IMPOSSIBLE。
2.限制条件如果不满足的话||第一条发生的话,记得把剩余的限制条件读完再输出。
3.我们其实可以简化,我们其实根本不需要源汇点,于是它其实可以转换成无源汇上下界网络流可行流。
原因:最开始建源汇点的时候我们发现它只连了上下界相同的边,相当于没连,以致到后来跑可行流的时候它根本不会做出任何贡献,所以大可以删掉。
4.IMPOSSIBLE不要打错……
5.ZOJ选手注意,不能填负数,最后一行不能有两个回车。
- #include<cstdio>
- #include<iostream>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- typedef long long ll;
- const int N=;
- const int M=;
- const int INF=1e9;
- inline int read(){
- int X=,w=;char ch=;
- while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
- while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
- return w?-X:X;
- }
- struct node{
- int nxt,to,w;
- }edge[M];
- int head[N],du[N],up[][],low[][];
- int cnt=-,S,T;
- bool die[][];
- inline void add(int u,int v,int w){
- cnt++;
- edge[cnt].to=v;
- edge[cnt].w=w;
- edge[cnt].nxt=head[u];
- head[u]=cnt;
- return;
- }
- int lev[N],cur[N],dui[N];
- bool bfs(int k){
- int r=;
- for(int i=;i<=k;i++){
- lev[i]=-;
- cur[i]=head[i];
- }
- dui[]=S,lev[S]=;
- int u,v;
- for(int l=;l<=r;l++){
- u=dui[l];
- for(int e=head[u];e!=-;e=edge[e].nxt){
- v=edge[e].to;
- if(edge[e].w>&&lev[v]==-){
- lev[v]=lev[u]+;
- r++;
- dui[r]=v;
- if(v==T)return ;
- }
- }
- }
- return ;
- }
- int dinic(int u,int flow,int k){
- if(u==k)return flow;
- int res=,delta;
- for(int &e=cur[u];e!=-;e=edge[e].nxt){
- int v=edge[e].to;
- if(edge[e].w>&&lev[u]<lev[v]){
- delta=dinic(v,min(edge[e].w,flow-res),k);
- if(delta>){
- edge[e].w-=delta;
- edge[e^].w+=delta;
- res+=delta;
- if(res==flow)break;
- }
- }
- }
- if(res!=flow)lev[u]=-;
- return res;
- }
- inline void init(int m,int n){
- memset(head,-,sizeof(head));
- memset(du,,sizeof(du));
- memset(die,,sizeof(die));
- for(int i=;i<=m;i++){
- for(int j=;j<=n;j++){
- up[i][j]=INF;
- low[i][j]=;
- }
- }
- cnt=-;
- return;
- }
- inline char getc(){
- char ch=' ';
- while(ch==' ')ch=getchar();
- return ch;
- }
- int main(){
- int t=read(),num=;
- while(t--){
- num++;
- if(num>)puts("");
- int m=read(),n=read();
- init(m,n);
- int tot=;
- for(int i=;i<=m;i++){
- int h=read();
- du[i]+=h;
- tot+=h;
- }
- for(int i=;i<=n;i++){
- int l=read();
- du[i+m]-=l;
- tot-=l;
- }
- int c=read();
- bool flag=;
- for(int i=;i<=c;i++){
- int r=read(),q=read(),a,b;
- char ch=getc();
- int v=read();
- if(ch=='<'){a=;b=--v;}
- else if(ch=='>'){a=++v;b=INF;}
- else a=b=v;
- if(!r&&!q){
- for(int j=;j<=m&&flag;j++){
- for(int k=;k<=n&&flag;k++){
- if(die[j][k]&&(low[j][k]>b||low[j][k]<a)){
- flag=;
- break;
- }
- if(ch=='='){up[j][k]=low[j][k]=v;die[j][k]=;}
- else if(ch=='>')low[j][k]=max(low[j][k],v);
- else up[j][k]=min(up[j][k],v);
- if(low[j][k]>up[j][k])flag=;
- }
- }
- }else if(!r){
- for(int j=;j<=m&&flag;j++){
- if(die[j][q]&&(low[j][q]>b||low[j][q]<a)){
- flag=;
- break;
- }
- if(ch=='='){up[j][q]=low[j][q]=v;die[j][q]=;}
- else if(ch=='>')low[j][q]=max(low[j][q],v);
- else up[j][q]=min(up[j][q],v);
- if(low[j][q]>up[j][q])flag=;
- }
- }else if(!q){
- for(int k=;k<=n&&flag;k++){
- if(die[r][k]&&(low[r][k]>b||low[r][k]<a)){
- flag=;
- break;
- }
- if(ch=='='){up[r][k]=low[r][k]=v;die[r][k]=;}
- else if(ch=='>')low[r][k]=max(low[r][k],v);
- else up[r][k]=min(up[r][k],v);
- if(low[r][k]>up[r][k])flag=;
- }
- }else{
- if(die[r][q]&&(low[r][q]>b||low[r][q]<a)){
- flag=;
- }
- if(ch=='='){up[r][q]=low[r][q]=v;die[r][q]=;}
- else if(ch=='>')low[r][q]=max(low[r][q],v);
- else up[r][q]=min(up[r][q],v);
- if(low[r][q]>up[r][q])flag=;
- }
- }
- if(!flag||tot!=){
- puts("IMPOSSIBLE");
- continue;
- }
- for(int i=;i<=m;i++){
- for(int j=;j<=n;j++){
- add(i,j+m,up[i][j]-low[i][j]);
- add(j+m,i,);
- du[i]-=low[i][j];
- du[j+m]+=low[i][j];
- }
- }
- S=m+n+;T=S+;
- int ans=,full=;
- for(int i=;i<=m+n;i++){
- if(du[i]>){
- add(S,i,du[i]);
- add(i,S,);
- full+=du[i];
- }else if(du[i]<){
- add(i,T,-du[i]);
- add(T,i,);
- }
- }
- while(bfs(T))ans+=dinic(S,INF,T);
- if(ans!=full)puts("IMPOSSIBLE");
- else{
- for(int i=;i<=m;i++){
- for(int j=;j<=n;j++){
- int id=((i-)*n+j)*-;
- printf("%d",low[i][j]+edge[id].w);
- if(j!=n)putchar(' ');
- }
- puts("");
- }
- }
- }
- return ;
- }
ZOJ1994 & POJ2396:Budget——题解的更多相关文章
- POJ2396 Budget [有源汇上下界可行流]
POJ2396 Budget 题意:n*m的非负整数矩阵,给出每行每列的和,以及一些约束关系x,y,>=<,val,表示格子(x,y)的值与val的关系,0代表整行/列都有这个关系,求判断 ...
- poj2396 Budget&&ZOJ1994 Budget[有源汇上下界可行流]
Budget Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge We are supposed to make ...
- POJ2396 Budget 【带下界的最大流】
Budget Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5962 Accepted: 2266 Special ...
- POJ2396:Budget(带下界的网络流)
Budget Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8946 Accepted: 3327 Special ...
- POJ2396 Budget
Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 7401 Accepted: 2764 Special Judge D ...
- poj2396 Budget 上下界可行流
Budget:http://poj.org/problem?id=2396 题意: 给定一个棋盘,给定每一行每一列的和,还有每个点的性质.求一个合理的棋盘数值放置方式. 思路: 比较经典的网络流模型, ...
- POJ2396 Budget(有源汇流量有上下界网络的可行流)
题目大概给一个有n×m个单元的矩阵,各单元是一个非负整数,已知其每行每列所有单元的和,还有几个约束条件描述一些单元是大于小于还是等于某个数,问矩阵可以是怎样的. 经典的流量有上下界网络流问题. 把行. ...
- poj2396 Budget(有源汇上下界可行流)
[题目链接] http://poj.org/problem?id=2396 [题意] 知道一个矩阵的行列和,且知道一些格子的限制条件,问一个可行的方案. [思路] 设行为X点,列为Y点,构图:连边(s ...
- 【POJ2396】Budget(上下界网络流)
Description We are supposed to make a budget proposal for this multi-site competition. The budget pr ...
随机推荐
- Java: Replace a string from multiple replaced strings to multiple substitutes
Provide helper methods to replace a string from multiple replaced strings to multiple substitutes im ...
- 【selenium】selenium全分享
第一节:selenium基础 [http://note.youdao.com/noteshare?id=43603fb53593bfc15c28bc358a3fa6ec] 目录: selenium简介 ...
- ISE 14.7安装教程最新版(Win10安装)——解决Win10安装完后打不开快捷方式的方法
ISE 14.7安装教程最新版(Win10安装) Xilinx ISE是一款世界著名的硬件设计软件,它为设计流程的每一步都提供了直观的生产力增强工具,覆盖从系统级设计探索.软件开发和基于HDL硬件设计 ...
- 1.1.0 Unity零基础入门2——Roll a Ball
1. 游戏界面 2.代码 //FoodRotate - - 控制cube旋转 using System.Collections; using System.Collections.Generic; u ...
- 微服务框架Dubbo与Springcloud的区别
微服务框架Dubbo与Springcloud的区别 微服务主要的优势如下: 1.降低复杂度 将原来偶合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累.每一个微服务专注于单一功能,并通过定 ...
- 统计hive库表在具体下所有分区大小
1 查询具体表分区大小,以字节展示 hadoop fs -du /user/hive/warehouse/treasury.db/dm_user_excercise > dm_user_exce ...
- Oracle存储过程练习题
1.1.创建一个过程,能向dept表中添加一个新记录.(in参数) 创建过程 create or replace procedure insert_dept ( num_dept in number, ...
- [C++]STL中的容器
C++11 STL中的容器 一.顺序容器: vector:可变大小数组: deque:双端队列: list:双向链表: forward_list:单向链表: array:固定大小数组: string: ...
- 基于MTCNN多任务级联卷积神经网络进行的人脸识别 世纪晟人脸检测
神经网络和深度学习目前为处理图像识别的许多问题提供了最佳解决方案,而基于MTCNN(多任务级联卷积神经网络)的人脸检测算法也解决了传统算法对环境要求高.人脸要求高.检测耗时高的弊端. 基于MTCNN多 ...
- 各类4G手机进入工参模式查看手机信息
随着移动4G正式商用,LTE网络建设日益完善,LTE用户日趋增多,通过进入其工程模式读取服务小区电平RSRP.物理小区标识PCI和频点号等基本信息的方式来判断测试点信号质量的优劣.由于市场上商用终端品 ...