hdoj 3666 THE MATRIX PROBLEM

類型:差分約束

題目:http://acm.hdu.edu.cn/showproblem.php?pid=3666

來源:2010 Asia Regional Harbin

思路:對於題目容易得到: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;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章