Budget
Time Limit: 3000MS | Memory Limit: 64M | |||
Special Judge |
Description
We are supposed to make a budget proposal for this multi-site competition. The budget proposal is a matrix where the rows represent different kinds of expenses and the columns represent different sites. We had a meeting about this, some time ago where we discussed the sums over different kinds of expenses and sums over different sites. There was also some talk about special constraints: someone mentioned that Computer Center would need at least 2000K Rials for food and someone from Sharif Authorities argued they wouldn't use more than 30000K Rials for T-shirts. Anyway, we are sure there was more; we will go and try to find some notes from that meeting.
And, by the way, no one really reads budget proposals anyway, so we'll just have to make sure that it sums up properly and meets all constraints.
And, by the way, no one really reads budget proposals anyway, so we'll just have to make sure that it sums up properly and meets all constraints.
Input
The first line of the input contains an integer N, giving the number of test cases. The next line is empty, then, test cases follow: The first line of each test case contains two integers, m and n, giving the number of rows and columns (m <= 200, n <= 20). The second line contains m integers, giving the row sums of the matrix. The third line contains n integers, giving the column sums of the matrix. The fourth line contains an integer c (c < 1000) giving the number of constraints. The next c lines contain the constraints. There is an empty line after each test case.
Each constraint consists of two integers r and q, specifying some entry (or entries) in the matrix (the upper left corner is 1 1 and 0 is interpreted as "ALL", i.e. 4 0 means all entries on the fourth row and 0 0 means the entire matrix), one element from the set {<, =, >} and one integer v, with the obvious interpretation. For instance, the constraint 1 2 > 5 means that the cell in the 1st row and 2nd column must have an entry strictly greater than 5, and the constraint 4 0 = 3 means that all elements in the fourth row should be equal to 3.
Each constraint consists of two integers r and q, specifying some entry (or entries) in the matrix (the upper left corner is 1 1 and 0 is interpreted as "ALL", i.e. 4 0 means all entries on the fourth row and 0 0 means the entire matrix), one element from the set {<, =, >} and one integer v, with the obvious interpretation. For instance, the constraint 1 2 > 5 means that the cell in the 1st row and 2nd column must have an entry strictly greater than 5, and the constraint 4 0 = 3 means that all elements in the fourth row should be equal to 3.
Output
For each case output a matrix of non-negative integers meeting the above constraints or the string "IMPOSSIBLE" if no legal solution exists. Put
one empty line between matrices.
Sample Input
2 2 3 8 10 5 6 7 4 0 2 > 2 2 1 = 3 2 3 > 2 2 3 < 5 2 2 4 5 6 7 1 1 1 > 10
Sample Output
2 3 3 3 3 4 IMPOSSIBLE
————————————————————忐忑的分割线————————————————————
前言:POJ上数据非常水,过了之后交到ZOJ上WA,调试了一下午 发现竟然是因为u == 0 && v == 0的情况枚举的时候少写了一个等于号……
思路:建图的时候要注意一下。
显然各行各列分别是顶点。从行流向列的话,没有上界的边上界是INF,那么怎么约束流量呢?各行之和的总和就是源点。源点需要向每一行连接一条边,容量恰好是各行之和。列同理。流向汇点。
这时候需要转换成无源汇的图。直接无视源点和汇点即可。它们的作用仅仅是提供流入的下界和或者流出的下界和。
之后建立超级源点和超级汇点,建立伴随网络,建图方法依旧是:原图拆边为上下界之差、流入该点下界和 - 流出该点下界和。
P.S. 传统的方法不是无视,而是另外添加一条从原始汇点向原始源点之间的边,值为INF,这样就可以保证原始源点、原始汇点和其它的点一样符合流量平衡条件。我这种方法没有丢弃任何约束条件,因此也正确。
代码如下:
/*
ID: j.sure.1
PROG:
LANG: C++
*/
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <climits>
#include <iostream>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
/****************************************/
const int R = 222, C = 22, N = 333, M = 44444;
int tot, S, T, head[N], cur[N], lev[N], q[N], s[N];
struct Node {
int u, v, w;
int next;
}edge[M];
int r, c, sum_r[R], sum_c[C], b[R][C], h[R][C];
void init()
{
tot = 0; memset(head, -1, sizeof(head));
}
void add(int u, int v, int w)
{
edge[tot].u = u; edge[tot].v = v; edge[tot].w = w;
edge[tot].next = head[u]; head[u] = tot++;
}
bool bfs()
{
memset(lev, -1, sizeof(lev));
int fron = 0, rear = 0;
lev[S] = 0;
q[rear++] = S;
while(fron < rear) {
int u = q[fron%N]; fron++;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if(edge[i].w && lev[v] == -1) {
lev[v] = lev[u] + 1;
q[rear%N] = v; rear++;
if(v == T) return true;
}
}
}
return false;
}
void Dinic()
{
while(bfs()) {
memcpy(cur, head, sizeof(head));
int u = S, top = 0;
while(1) {
if(u == T) {
int mini = INF, loc;
for(int i = 0; i < top; i++) {
if(mini > edge[s[i]].w) {
mini = edge[s[i]].w;
loc = i;
}
}
for(int i = 0; i < top; i++) {
edge[s[i]].w -= mini;
edge[s[i]^1].w += mini;
}
top = loc;
u = edge[s[top]].u;
}
int &i = cur[u];
for(; ~i; i = edge[i].next) {
int v = edge[i].v;
if(edge[i].w && lev[v] == lev[u] + 1) break;
}
if(~i) {
s[top++] = i;
u = edge[i].v;
}
else {
if(!top) break;
lev[u] = -1;
u = edge[s[--top]].u;
}
}
}
}
void getlim(int u, int v, char op, int w)
{
switch(op)
{
case '=': b[u][v] = h[u][v] = w; break;
case '<': h[u][v] = min(h[u][v], w - 1); break;
case '>': b[u][v] = max(b[u][v], w + 1); break;
}
}
void build()
{
S = 0; T = r+c+1;
for(int i = 1; i <= r; i++) {
for(int j = 1; j <= c; j++) {
add(i, j+r, h[i][j] - b[i][j]);
add(j+r, i, 0);
}
}
for(int i = 1; i <= r+c; i++) {
int f = i <= r ? sum_r[i] : -sum_c[i-r];
if(i <= r) for(int j = 1; j <= c; j++) {
f -= b[i][j];
}
else for(int j = 1; j <= r; j++) {
f += b[j][i-r];
}
if(f > 0) {
add(S, i, f); add(i, S, 0);
}
else if(f < 0) {
add(i, T, -f); add(T, i, 0);
}
}
}
bool judge()
{
for(int i = head[S]; ~i; i = edge[i].next) {
if(edge[i].w) return false;
}//检查可行流
for(int i = 0; i < r*c; i++) {
int x = edge[i<<1].u, y = edge[i<<1].v;
printf("%d", edge[i<<1|1].w + b[x][y-r]);
if(i != c-1 && i != r*c-1) printf(" ");
else puts("");
}
return true;
}
int main()
{
#ifdef J_Sure
// freopen("000.in", "r", stdin);
// freopen(".out", "w", stdout);
#endif
int TT; bool kase = 0;
scanf("%d", &TT);
while(TT--) {
int m, u, v, w;
char op;
scanf("%d%d", &r, &c);
for(int i = 1; i <= r; i++) {
scanf("%d", &sum_r[i]);
}
for(int i = 1; i <= c; i++) {
scanf("%d", &sum_c[i]);
}
for(int i = 1; i <= r; i++) {
for(int j = 1; j <= c; j++) {
b[i][j] = 0; h[i][j] = INF;
}
}
scanf("%d", &m);
while(m--) {
scanf("%d%d %c%d", &u, &v, &op, &w);
if(!u && !v) {
for(int i = 1; i <= r; i++) {
for(int j = 1; j <= c; j++) {
getlim(i, j, op, w);
}
}
}
else if(!u) {
for(int i = 1; i <= r; i++) {
getlim(i, v, op, w);
}
}
else if(!v) {
for(int j = 1; j <= c; j++) {
getlim(u, j, op, w);
}
}
else getlim(u, v, op, w);
}
init();
build();
Dinic();
if(kase) puts("");
kase = 1;
if(!judge()) puts("IMPOSSIBLE");
}
return 0;
}