|hdu 3666|差分约束|THE MATRIX PROBLEM

hdu 3666

由题意可知,

L<=C(i,j)ai/bj<=U

可以都除以 C(i,j) , 得
L/C(i,j)<=ai/bj<=U/C(i,j)

此时都是除法,不满足差分约束

看两个性质
log(a/b)=log(a)log(b)
log(ab)=log(a)+log(b)

那么原式可以变为

log(L/C(i,j))<=log(ai/bj)<=log(U/C(i,j))

log(L)log(C(i,j))<=log(ai)log(bj)<=log(U)log(C(i,j))

ai,bj 看做是一个元素,就可以建立差分约束系统求解是否存在

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值