【题意】:给出一个N*M的矩阵C,C中每个元素都是正整数且不超过1000.问是否存在一个长度为N的序列a1,a2,……,a
N和一个长度为M的序列b1,b2,……,b
M使得矩阵C中的每一个元素C
ij满足 L <= C
ij * a
i / b
j <= U。
【题解】:从题目中可以抽离出N * M个不等式,然后题目又要我们判断可行解,这样子很容易就想到差分约束系统。对于这个不等式,我们需要做点转化,用一个log化简一下即可。
L <= C
ij * a
i / b
j <= U => log L - log C
ij <= log a
i - log b
j <= log U - log C
ij.
然后构图找判负环即可,但是这个N*M高达800,所以queue的spfa会TLE,这里采用stack的spfa。
【代码】:
1 #include "iostream"
2 #include "cstring"
3 #include "cstdio"
4 #include "cmath"
5 using namespace std;
6 #define maxn 1000
7 #define maxm 1000000
8 const double inf = 1 << 30;
9 int n, m, s;
10 double l, u;
11 bool visit[maxn];
12 int eh[maxn], tot;
13 double dist[maxn];
14 struct Edge {
15 int u, v;
16 double cost;
17 int next;
18 }et[maxm];
19
20 void init() {
21 tot = 0;
22 memset(eh, -1, sizeof(eh));
23 }
24
25 void addedge(int u, int v, double cost) {
26 Edge e = {u, v, cost, eh[u]};
27 et[tot] = e;
28 eh[u] = tot++;
29 }
30 bool instack[maxn];
31 bool dfs_spfa(int u) {
32 if(instack[u]) return false;
33 instack[u] = true;
34 visit[u] = true;
35 for(int i = eh[u]; i != -1; i = et[i].next) {
36 int v = et[i].v;
37 double cost = et[i].cost;
38 if(dist[v] > dist[u] + cost) {
39 dist[v] = dist[u] + cost;
40 if(!dfs_spfa(v)) return false;
41 }
42 }
43 instack[u] = false;
44 return true;
45 }
46
47 bool solve() {
48 memset(visit, false, sizeof(visit));
49 memset(instack, false, sizeof(instack));
50 memset(dist, 0, sizeof(dist));
51 for(int i = 1; i <= n + m; i++) {
52 if(!visit[i])
53 if(!dfs_spfa(i)) return false;
54 }
55 return true;
56 }
57
58 int main() {
59 double tmp;
60 while(scanf("%d%d%lf%lf", &n, &m, &l, &u) != EOF) {
61 init();
62 for(int i = 1; i <= n; i++) {
63 for(int j = 1; j <= m; j++) {
64 scanf("%lf", &tmp);
65 addedge(j + n, i, log(u / tmp));
66 addedge(i, j + n, -log(l / tmp));
67 }
68 }
69 if(solve()) printf("YES\n");
70 else printf("NO\n");
71 }
72
73 return 0;
74 }