Time Limit: 3000MS | Memory Limit: 65536K | |||
Total Submissions: 5621 | Accepted: 2140 | Special Judge |
Description
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
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
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
題意:有一個矩陣,n行m列,給出每行元素的和、每列元素的和,並且給出c個約束,每個約束(u, v) = a代表元素(u, v)必須等於a(>或<時以此類推),若u=0,則代表第v列元素必須全部=(或>、<)a。問是否存在一個滿足所有約束條件的矩陣,若存在,輸出這個矩陣。
思路:設源點s,匯點t,每行和每列看成是一個結點,s到行結點i連一條[sum[i], sum[i]]的邊,列節點i到t連一條[sum[i], sum[i]]的邊,然後行結點到列節點連滿足上下界的邊,再虛設一個超級源點ss和超級匯點tt,求一次可行流就可以了。
AC代碼:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <ctime>
#include <vector>
#include <algorithm>
#define ll long long
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)
using namespace std;
const int INF = 1e9;
const int maxn = 505;
struct Edge
{
int u, v, cap, flow, next;
} et[maxn * maxn];
int low[maxn], cnt[maxn], dis[maxn], pre[maxn], cur[maxn], eh[maxn], du[maxn];
int L[maxn][maxn], R[maxn][maxn];
int n, m, s, t, num, ss, tt, sum1, sum2, sum;
void init()
{
memset(eh, -1, sizeof(eh));
memset(du, 0, sizeof(du));
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
{
L[i][j] = 0;
R[i][j] = INF;
}
num = sum1 = sum2 = sum = 0;
}
void add(int u, int v, int cap, int flow)
{
Edge e = {u, v, cap, flow, eh[u]};
et[num] = e;
eh[u] = num++;
}
void addedge(int u, int v, int cap)
{
add(u, v, cap, 0);
add(v, u, 0, 0);
}
int isap(int s, int t, int nv)
{
int u, v, now, flow = 0;
memset(low, 0, sizeof(low));
memset(cnt, 0, sizeof(cnt));
memset(dis, 0, sizeof(dis));
for(u = 0; u <= nv; u++) cur[u] = eh[u];
low[s] = INF, cnt[0] = nv, u = s;
while(dis[s] < nv)
{
for(now = cur[u]; now != -1; now = et[now].next)
if(et[now].cap - et[now].flow && dis[u] == dis[v = et[now].v] + 1) break;
if(now != -1)
{
cur[u] = pre[v] = now;
low[v] = min(low[u], et[now].cap - et[now].flow);
u = v;
if(u == t)
{
for(; u != s; u = et[pre[u]].u)
{
et[pre[u]].flow += low[t];
et[pre[u]^1].flow -= low[t];
}
flow += low[t];
low[s] = INF;
}
}
else
{
if(--cnt[dis[u]] == 0) break;
dis[u] = nv, cur[u] = eh[u];
for(now = eh[u]; now != -1; now = et[now].next)
if(et[now].cap - et[now].flow && dis[u] > dis[et[now].v] + 1)
dis[u] = dis[et[now].v] + 1;
cnt[dis[u]]++;
if(u != s) u = et[pre[u]].u;
}
}
return flow;
}
bool judge()
{
if(sum1 != sum2) return false;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
if(L[i][j] > R[i][j]) return false;
addedge(i, j + n, R[i][j] - L[i][j]);
du[i] -= L[i][j];
du[j + n] += L[i][j];
}
return true;
}
void solve()
{
ss = t + 1, tt = t + 2;
sum = 0;
for(int i = 0; i <= t; i++)
{
if(du[i] > 0)
{
addedge(ss, i, du[i]);
sum += du[i];
}
else if(du[i] < 0) addedge(i, tt, -du[i]);
}
addedge(t, s, INF);
int tmp = isap(ss, tt, tt + 1);
if(tmp != sum)
{
printf("IMPOSSIBLE\n");
return;
}
int cc = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j < m; j++)
{
printf("%d ", et[cc].flow + L[i][j]);
cc += 2;
}
printf("%d\n", et[cc].flow + L[i][m]);
cc += 2;
}
}
int main()
{
int ca, a, c, nn, mm;
char ch[5];
scanf("%d", &ca);
while(ca--)
{
scanf("%d%d", &n, &m);
init();
s = 0, t = n + m + 1;
for(int i = 1; i <= n; i++)
{
scanf("%d", &c); //行結點[c, c]
du[s] -= c;
du[i] += c;
sum1 += c;
}
for(int i = n + 1; i <= n + m; i++)
{
scanf("%d", &c); //列節點[c, c]
du[i] -= c;
du[t] += c;
sum2 += c;
}
scanf("%d", &c);
while(c--)
{
scanf("%d%d%s%d", &nn, &mm, ch, &a);
int r1 = nn, r2 = nn, c1 = mm, c2 = mm;
if(nn == 0) r1 = 1, r2 = n;
if(mm == 0) c1 = 1, c2 = m;
for(int i = r1; i <= r2; i++)
for(int j = c1; j <= c2; j++)
{
if(ch[0] == '=')
{
L[i][j] = max(L[i][j], a);
R[i][j] = min(R[i][j], a);
}
else if(ch[0] == '>') L[i][j] = max(L[i][j], a + 1);
else R[i][j] = min(R[i][j], a - 1);
}
}
if(judge()) solve();
else printf("IMPOSSIBLE\n");
puts("");
}
return 0;
}