HDU3666--差分约束

思路:
根据题意可得,L<=a[i]*g[i][j]/b[j]<=U,看到不等式,马上想到差分约束
将上式移项得L/g[i][j]<=a[i]/b[j]<=U/g[i][j],再取对数log(L/g[i][j])<=log(a[i])-log(b[j])<=log(U/g[i][j])
最后构造<=的不等式,用spfa跑最短路,若存在负环,说明无解,输出NO,反之输出YES
注:有个坑点,这题对时间复杂度要求较高,所以spfa只能算到sqrt(n+m),否则就会被T飞

/*
HDU--3666
*/
#include
using namespace std;
const int N = 805;
const int INF = 0x3f3f3f3f;
int n, m, L, U;
int head[N], tot;
double dis[N];
bool vis[N];
int cnt[N];
struct Edge {
	int to;
	int nxt;
	double w;
}e[N*N];
void add(int u, int v, double w) {
	e[++tot].nxt = head[u];
	e[tot].to = v;
	e[tot].w = w;
	head[u] = tot;
}
bool spfa(int s) {
	for (int i = 1; i <= n + m; i++) {
		vis[i] = false;
		cnt[i] = 0;
		dis[i] = INF;
	}
	vis[s] = true;
	cnt[s] = 0;
	dis[s] = 0;
	queueq;
	q.push(s);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		vis[u] = false;
		for (int v,i = head[u]; i != -1; i = e[i].nxt) {
			v = e[i].to;
			if (dis[v] > dis[u] + e[i].w) {
				dis[v] = dis[u] + e[i].w;
				if (!vis[v]) {
					vis[v] = true;
					cnt[v]++;
					q.push(v);
					if (cnt[v] > sqrt(n+m))return false;
				}
			}
		}
	}
	return true;
}
int main() {
	while (scanf("%d%d%d%d", &n, &m, &L, &U) != EOF) {
		memset(head, -1, sizeof(head));
		tot = 0;
		for (int x, i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				scanf("%d", &x);
				add(j + n, i, log((U + 0.0) / x));
				add(i, j + n, -log((L + 0.0) / x));
			}
		}
		printf(spfa(1) ? "YES\n" : "NO\n");
	}
	return 0;
}

你可能感兴趣的:(HDU3666--差分约束)