類型:差分約束
題目:http://acm.hdu.edu.cn/showproblem.php?pid=3666
思路:對於題目容易得到:L <= c[i][j] * a[i] / b[j] <= U,然後有:c[i][j] * a[i] - U * b[j] <= 0 和 L * b[j] - c[i][j] * a[i] <= 0,聯想到差分約束系統。
對於乘法的消除可以使用對數的性質。得到:log(a[i]) - log(b[j]) <= log(U / c[i][j]),log(b[j]) - log(a[i]) <= log(c[i][j] / L) 【即dist[i] - dist[j] <= w形式】
添加邊:(j + n, i, log(U / c[i][j])) 和 (i, j + N, log(c[i][j] / L)) 【行、列屬不同點】,然後判斷負環【dfs_spfa實現:避免tle】
參考:http://www.cppblog.com/y346491470/articles/158557.html
《spfa算法的優化及應用》論文
// hdoj 3666 THE MATRIX PROBLEM
// tle wa wa ac 296MS 5316K
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define FORD(i,a,b) for(i = (a); i > (b); --i)
#define FORDE(i,a,b) for(i = (a); i >= (b); --i)
#define CLR(a,b) memset(a,b,sizeof(a))
#define PB(x) push_back(x)
const int MAXN = 1000;
const int MAXM = 640010;
const int hash_size = 25000002;
const int INF = 0x7f7f7f7f;
int n, m, l, u, num_v, cnt;
bool vis[MAXN], instack[MAXN];
int head[MAXN], cnt0[MAXN], q[MAXM];
double dist[MAXN];
struct edge {
int nxt, v;
double w;
}p[MAXM];
void addedge(int u, int v, double w) {
p[cnt].v = v;
p[cnt].w = w;
p[cnt].nxt = head[u];
head[u] = cnt++;
}
void init() {
int i, j, x;
CLR(head, -1);
cnt = 0;
num_v = n + m;
FORE(i, 1, n) FORE(j, 1, m) {
scanf("%d", &x);
addedge(j + n, i, log(u * 1.0 / x));
addedge(i, j + n, log(x * 1.0 / l));
}
}
bool dfs_spfa(int u) {
int i, v;
if(instack[u])
return false;
instack[u] = true;
vis[u] = true;
for(i = head[u]; i != -1; i = p[i].nxt) {
v = p[i].v;
if(dist[v] > dist[u] + p[i].w) {
dist[v] = dist[u] + p[i].w;
if(!dfs_spfa(v))
return false;
}
}
instack[u] = false;
return true;
}
bool solve() {
int i;
CLR(vis, false);
CLR(instack, false);
CLR(dist, 0);
FORE(i, 1, num_v) {
if(!vis[i])
if(!dfs_spfa(i))
return false;
}
return true;
}
int main() {
while(scanf("%d %d %d %d", &n, &m, &l, &u) != EOF) {
init();
bool sign = solve();
if(sign)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}