【题目链接】

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. button 事件属性

  2. Shell最多支持多少个参数

    本文转自:http://www.jb51.net/article/56548.htm   这篇文章主要介绍了Shell最多支持多少个参数?本文是对Shell最多可以输入多少个参数的一篇测试文章,需要的 ...

  3. Hibernate 主键策略

    Hibernate主键生成策略 .自动增长identity 适用于MySQL.DB2.MS SQL Server,采用数据库生成的主键,用于为long.short.int类型生成唯一标识 使用SQL ...

  4. linux用dd测试磁盘速度

    [root@localhost ~]# time dd if=/dev/zero bs=1024 count=1000000 of=/1Gb.file记录了1000000+0 的读入记录了100000 ...

  5. apk反编译(2)smali语言及文件

    Smali语言是Davlik的虚拟机使用的一种语言,用toolapk反编译apk后,可以见到大量的.smali文件. 可以按照smali语法对其修改,然后重新生成一个未签名的apk. 下面是一个示例: ...

  6. hdu 2986 Ballot evaluation (模拟)

    题目 上次比赛的题目,好长时间了. 这几天感冒了很难受, 直到现在才整理, 上次比赛的时候,出了各种错误,   ,,,样例都没过,题目读的也很差,今天做的时候, 看了一下网上的,发现一个代码特别简洁, ...

  7. velocity加减运算注意格式 ,加减号的左右都要有空格

    velocity加减运算注意格式 ,加减号的左右都要有空格 #set( $left= $!biz.value - $vMUtils.getReturnMoney($!biz.billBuy) )

  8. POJ 2455 - Secret Milking Machine

    原题地址:http://poj.org/problem?id=2455 题目大意:给出一个N个点的无向图,中间有P条边,要求找出从1到n的T条通路,满足它们之间没有公共边,并使得这些通路中经过的最长的 ...

  9. 宏buf_pool_struct

    typedef struct buf_pool_struct buf_pool_t; /** @brief The buffer pool structure. NOTE! The definitio ...

  10. Qt之进程间通信(共享内存)

    简述 上一节中,我们分享下如何利用Windows消息机制来进行不同进程间的通信.但是有很多局限性,比如:不能跨平台,而且必须两个进程同时存在才可以,要么进程A发了消息谁接收呢? 下面我们来分享另外一种 ...