由题意可知, $$L <= C(i,j) * a_i/b_j <= U$$
可以都除以$C(i,j)$, 得 $$L/C(i,j) <= a_i/b_j <= U/C(i,j)$$
此时都是除法,不满足差分约束
看两个性质
$log(a/b) = log(a) - log(b)$
$log(a*b) = log(a) + log(b)$
那么原式可以变为
$$log(L/C(i,j)) <= log(a_i/b_j) <= log(U/C(i,j))$$
$$log(L) - log(C(i,j)) <= log(a_i) - log(b_j) <= log(U) - log(C(i,j))$$
将$a_i, b_j$看做是一个元素,就可以建立差分约束系统求解是否存在
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#define ms(i, j) memset(i, j, sizeof i)
#define FN2 "hdu3666"
using namespace std;
const int MAXN = 400 * 400 + 5;
struct edge
{
int v;
double w;
}ed[MAXN*2];
int en;
vector<int> G[MAXN];
struct sdc
{
double dis[MAXN];
int cir[MAXN], vi[MAXN];
int n;
void init(int n)
{
en = 0;
this->n = n;
for (int i=1;i<=n;i++) G[i].clear();
}
void addedge(int x, int y, double c) // a - b <= c
{
en++, ed[en].v = x, ed[en].w = c, G[y].push_back(en);
}
int solve()
{
queue<int> q;
for (int i=1;i<=n;i++) dis[i] = 0, cir[i] = 1, vi[i] = true, q.push(i);
while (!q.empty())
{
int p = q.front(); q.pop(); vi[p] = false;
for (int i=0;i<G[p].size();i++)
{
int v = ed[G[p][i]].v;
double w = ed[G[p][i]].w;
if (dis[v]>dis[p]+w)
{
dis[v] = dis[p] + w;
if (!vi[v])
{
vi[v] = true;
cir[v]++; if (cir[v]>4) return false;//坑,>4只是卡的,>n会无限TLE TAT
q.push(v);
}
}
}
}
return true;
}
}sd;
int n, m;
double L, U, l_L, l_U;
void init()
{
sd.init(n*n);
l_L = log(L), l_U = log(U);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
double c, l_c; scanf("%lf", &c), l_c = log(c);
// a 1~n, b n+1~2n
sd.addedge(i, j+n, l_U-l_c);
sd.addedge(j+n, i, l_c-l_L);
}
}
}
void solve()
{
if (sd.solve()) printf("YES\n"); else printf("NO\n");
}
int main()
{
#ifndef ONLINE_JUDGE
freopen(FN2".in","r",stdin);
freopen(FN2".out","w",stdout);
#endif
while (scanf("%d%d%lf%lf", &n, &m, &L, &U)==4)
{
init();
solve();
}
return 0;
}