【题目链接】

http://poj.org/problem?id=2396

【题意】

知道一个矩阵的行列和,且知道一些格子的限制条件,问一个可行的方案。

【思路】

设行为X点,列为Y点,构图:连边(s,Xi,sumXi,sumXi)(Yi,t,sumYi,sumYi)(Xi,Yj,down[i][j],up[i][j])。

则问题就是求一个有源汇点st的上下界可行流。

类似于 无源无汇上下界可行流 ,添加附加源汇点ST,边权转化为up-down,由ST向每个点连边保持流量平衡。然后添加(t,s,inf),使得t的流出量与s的流入量保持相等,即等价于s为源点而t为汇点。

最后由S->T跑最大流。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 4e2+;
const int M = N*N+;
const int inf = 1e9; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int u,v,cap,flow;
Edge(int u=,int v=,int cap=,int flow=)
:u(u),v(v),cap(cap),flow(flow){}
};
struct Dinic {
int n,m,s,t;
int d[N],cur[N],vis[N];
vector<int> g[N];
vector<Edge> es;
queue<int> q;
void init(int n) {
this->n=n;
es.clear();
FOR(i,,n) g[i].clear();
}
void clear() {
FOR(i,,(int)es.size()-) es[i].flow=;
}
void AddEdge(int u,int v,int w) {
es.push_back(Edge(u,v,w,));
es.push_back(Edge(v,u,,));
m=es.size();
g[u].push_back(m-);
g[v].push_back(m-);
}
int bfs() {
memset(vis,,sizeof(vis));
q.push(s); d[s]=; vis[s]=;
while(!q.empty()) {
int u=q.front(); q.pop();
FOR(i,,(int)g[u].size()-) {
Edge& e=es[g[u][i]];
int v=e.v;
if(!vis[v]&&e.cap>e.flow) {
vis[v]=;
d[v]=d[u]+;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int u,int a) {
if(u==t||!a) return a;
int flow=,f;
for(int& i=cur[u];i<g[u].size();i++) {
Edge& e=es[g[u][i]];
int v=e.v;
if(d[v]==d[u]+&&(f=dfs(v,min(a,e.cap-e.flow)))>) {
e.flow+=f;
es[g[u][i]^].flow-=f;
flow+=f; a-=f;
if(!a) break;
}
}
return flow;
}
int MaxFlow(int s,int t) {
this->s=s,this->t=t;
int flow=;
while(bfs()) {
memset(cur,,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
} dc; int n,m,flag;
int in[N],up[N][N],down[N][N]; void can(int x,int y,int v) {
if(v<down[x][y]||v>up[x][y]) flag=;
} int main()
{
int kase=read();
while(kase--)
{
memset(in,,sizeof(in));
n=read(),m=read();
flag=;
int x,s=n+m+,t=s+,S=t+,T=S+;
dc.init(n+m+);
FOR(i,,n) {
x=read(); in[s]-=x,in[i]+=x;
dc.AddEdge(s,i,);
}
FOR(i,,m) {
x=read(); in[n+i]-=x,in[t]+=x;
dc.AddEdge(i+n,t,);
}
int K=read();
FOR(i,,n+m+) FOR(j,,n+m+)
up[i][j]=,down[i][j]=-;
while(K--) {
char s[];
int x=read(),y=read(),z;
scanf("%s",s); z=read();
if(x== && y) {
FOR(i,,n) {
if(s[]=='=') can(i,y+n,z),up[i][y+n]=down[i][y+n]=z;
if(s[]=='<') up[i][y+n]=min(up[i][y+n],z-);
if(s[]=='>') down[i][y+n]=max(down[i][y+n],z+);
}
} else
if(x && y==) {
FOR(i,,m) {
if(s[]=='=') can(x,i+n,z),up[x][i+n]=down[x][i+n]=z;
if(s[]=='<') up[x][i+n]=min(up[x][i+n],z-);
if(s[]=='>') down[x][i+n]=max(down[x][i+n],z+);
}
} else
if(x== && y==) {
FOR(i,,n) FOR(j,,m) {
if(s[]=='=') can(i,j+n,z),up[i][j+n]=down[i][j+n]=z;
if(s[]=='<') up[i][j+n]=min(up[i][j+n],z-);
if(s[]=='>') down[i][j+n]=max(down[i][j+n],z+);
}
} else {
if(s[]=='=') can(x,y+n,z),up[x][y+n]=down[x][y+n]=z;
if(s[]=='<') up[x][y+n]=min(up[x][y+n],z-);
if(s[]=='>') down[x][y+n]=max(down[x][y+n],z+);
}
}
int cur=dc.es.size();
FOR(i,,n) FOR(j,,m) {
if(up[i][j+n]<down[i][j+n]) flag=;
dc.AddEdge(i,j+n,up[i][j+n]-down[i][j+n]);
in[i]-=down[i][j+n];
in[j+n]+=down[i][j+n];
}
dc.AddEdge(t,s,inf);
if(flag) { puts("IMPOSSIBLE"); continue; }
int sum=;
FOR(i,,t) {
if(in[i]>) dc.AddEdge(S,i,in[i]),sum+=in[i];
if(in[i]<) dc.AddEdge(i,T,-in[i]);
}
if(sum!=dc.MaxFlow(S,T)) { puts("IMPOSSIBLE"); continue; }
else {
FOR(i,,n) FOR(j,,m) {
printf("%d",dc.es[cur].flow+down[i][j+n]);
if(j!=m) putchar(' '); else puts("");
cur+=;
}
}
}
return ;
}

poj2396 Budget(有源汇上下界可行流)的更多相关文章

  1. POJ2396 Budget [有源汇上下界可行流]

    POJ2396 Budget 题意:n*m的非负整数矩阵,给出每行每列的和,以及一些约束关系x,y,>=<,val,表示格子(x,y)的值与val的关系,0代表整行/列都有这个关系,求判断 ...

  2. poj2396 Budget&&ZOJ1994 Budget[有源汇上下界可行流]

    Budget Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge We are supposed to make ...

  3. 有源汇上下界可行流(POJ2396)

    题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案. 源点向行,汇点向列,连一条上下界均为和的边. 对于某格的限制,从它所在行向所在列连其上下界的边. 求有源汇上下界可行流 ...

  4. 计蒜客 31447 - Fantastic Graph - [有源汇上下界可行流][2018ICPC沈阳网络预赛F题]

    题目链接:https://nanti.jisuanke.com/t/31447 "Oh, There is a bipartite graph.""Make it Fan ...

  5. poj2396有源汇上下界可行流

    题意:给一些约束条件,要求算能否有可行流,ps:刚开始输入的是每一列和,那么就建一条上下界相同的边,这样满流的时候就一定能保证流量相同了,还有0是该列(行)对另一行每个点都要满足约束条件 解法:先按无 ...

  6. 算法复习——有源汇上下界可行流(bzoj2396)

    题目: Description We are supposed to make a budget proposal for this multi-site competition. The budge ...

  7. ZOJ1994有源汇上下界可行流

    http://fastvj.rainng.com/contest/236779#problem/G Description: n 行 m 列 给你行和 与 列和 然后有Q个限制,表示特定单元格元素大小 ...

  8. bzoj 2406 矩阵 —— 有源汇上下界可行流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2406 这题,首先把题目那个式子的绝对值拆成两个限制,就成了网络流的上下界: 有上下界可行流原 ...

  9. bzoj千题计划158:bzoj2406: 矩阵(有源汇上下界可行流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2406 设矩阵C=A-B 最小化 C 一行或一列和的最大值 整体考虑一行或者一列的和 二分最大值 这样 ...

随机推荐

  1. 使用CAShapeLayer与UIBezierPath画出想要的图形

    使用CAShapeLayer与UIBezierPath可以实现不在view的drawRect方法中就画出一些想要的图形 步骤: 1.新建UIBezierPath对象bezierPath 2.新建CAS ...

  2. 从一点儿不会开始——Unity3D游戏开发学习(二) ——GUI控件之Button

    一些废话 我在上一篇“一点儿不会”的系列随笔中说大概一周会发个2~3篇关于Unity的学习笔记.可这就两周过去了,我还停留在一篇的进度上,主要是这两周发生了一些事情导致我更新缓慢.其实截至目前为止,上 ...

  3. SpringMVC,MyBatis商品的增删改查

    一.需求 商品的增删改查 二.工程结构 三.代码 1.Mapper层 (1) ItemsMapperCustom.java package com.tony.ssm.mapper; import ja ...

  4. 使用CXF暴露您的REST服务

    使用CXF暴露您的REST服务 REST应用服务器SpringBeanServlet  1.  前言 现在互联网Open API流行,将您的Web应用也可以开放Open API给其他第三方使用.达到一 ...

  5. [Linux 命令]df -h

    查看目前磁盘空间和使用情况 以更易读的方式显示

  6. Maven那点事儿(Eclipse版)

    Maven那点事儿(Eclipse版)   前言: 由于最近工作学习,总是能碰到Maven的源码.虽然平时工作并不使用Maven,但是为了学习一些源码,还是必须要了解下.这篇文章不是一个全面的Mave ...

  7. 1、Web容器的理解&Tomcat的安装与配置

    Web容器的理解 <Java Web开发实战经典——基础篇>一书中对Web容器这一概念阐述得很好,借用其观点对Web容器加以理解: 想要运行一个Java Web的程序,则必须有相应的Web ...

  8. Android开发之android:process=":remote"

    由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象.在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将 ...

  9. Git show-branch显示提交信息

    git中查看日志,我们用的比较多的就是 git log 以及带一些参数,如: 以一行显示提交日志: $ git log --pretty=oneline 显示最后的几次提交日志: $ git log ...

  10. 1651. Shortest Subchain(bfs)

    1651 终于A了 看这题容易想到最短路 看到错的很多 还特意注意了好几处 后来发现 必须按给出的顺序出边 想了想 这不就是BFS 然后就是各种细节 i->i+1ori->j(a[i]== ...