hdu3666 THE MATRIX PROBLEM --- 差分约束

这要是碰上现场赛我得被搞死 从RE到TLE到WA已疯。。

这题建图没有那么直接,通过给出的不等式关系一时想不到怎么建图

所以要对题目给的条件一定程度化简,将不等式两边取对数化简得到Sa-Sb<=c的形式

要注意w取double类型

其次,这题卡时间,根据经验加剪枝:

1、出队次数>sqrt(n)则判断有负环

2、统计总的入队次数,>2n则判断有负环

一般情况下不用这个,因为不严谨

下面两个spfa都是对的,手写队列稍快一点,上面第二个剪枝效果明显

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;

struct node
{
    int v;
    double w;
    int next;
}e[360010];
int n,m,h,head[810],inq[810],outq[810],q[50000];
double d[805];

void addedge(int a,int b,double c)
{
    e[h].v=b;
    e[h].w=c;
    e[h].next=head[a];
    head[a]=h++;
}

bool spfa(int s)
{
    int iq,i,top,k;
    for(i=0;i<=n;i++)
        d[i]=1000000000;
    memset(inq,0,sizeof inq);
    memset(outq,0,sizeof outq);
    d[s]=0;inq[s]=1;
    iq=0;i=0;
    q[iq++]=s;
    while(i!=iq)
    {
        top=q[i];
        inq[top]=0;
        outq[top]++;
        if(outq[top]>(int)sqrt(n*1.0)) return 0;
        k=head[top];
        while(k>=0)
        {
            if(d[e[k].v]-e[k].w>d[top])
            {
                d[e[k].v]=e[k].w+d[top];
                if(!inq[e[k].v])
                {
                    inq[e[k].v]=1;
                    q[iq++]=e[k].v;
                }
            }
            k=e[k].next;
        }
        i++;
    }
    return 1;
}

int spfa(int st)//邻接表 STL
{
    for(int i=0;i<=n;i++)
        d[i]=100000000;
    memset(inq,0,sizeof inq);
    memset(outq,0,sizeof outq);
    d[st]=0;inq[st]=1;
    queue<int> q;
    q.push(st);
    int cnt=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        inq[x]=0;
        outq[x]++;
        if(outq[x]>sqrt(n*1.0)+10) return 0;
        for(int i=head[x];i!=-1;i=e[i].next)
        {
            if(d[e[i].v]>d[x]+e[i].w)
            {
                d[e[i].v]=d[x]+e[i].w;
                if(!inq[e[i].v])
                {
                    cnt++;
                    if(cnt>((n+m)*2)) return 0;
                    inq[e[i].v]=1;
                    q.push(e[i].v);
                }
            }
        }
    }
    return 1;
}

int main()
{
    double x,ll,uu,l,u;
    int i,j;
    while(~scanf("%d%d%lf%lf",&n,&m,&l,&u))
    {
        memset(head,-1,sizeof head);
        h=0;
        ll=log(l);uu=log(u);
        for(i=0;i<n;i++)
            for(j=0;j<m;j++)
            {
                scanf("%lf",&x);
                addedge(i,j+n,log(x)-ll);
                addedge(j+n,i,uu-log(x));
            }
        n+=m;m+=m;
        if(spfa(0)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

hdu3666 THE MATRIX PROBLEM --- 差分约束

时间: 2024-10-12 15:48:59

hdu3666 THE MATRIX PROBLEM --- 差分约束的相关文章

HDU3666 THE MATRIX PROBLEM (差分约束+取对数去系数)(对退出情况存疑)

You have been given a matrix C N*M, each element E of C N*M is positive and no more than 1000, The problem is that if there exist N numbers a1, a2, … an and M numbers b1, b2, …, bm, which satisfies that each elements in row-i multiplied with ai and e

HDOJ 3666 THE MATRIX PROBLEM 差分约束

根据题意有乘除的关系,为了方便构图,用对数转化乘除关系为加减关系..... THE MATRIX PROBLEM Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7486    Accepted Submission(s): 1914 Problem Description You have been given a matrix CN

HDU 3666 THE MATRIX PROBLEM (差分约束)

题意:给定一个最大400*400的矩阵,每次操作可以将某一行或某一列乘上一个数,问能否通过这样的操作使得矩阵内的每个数都在[L,R]的区间内. 析:再把题意说明白一点就是是否存在ai,bj,使得l<=cij*(ai/bj)<=u (1<=i<=n,1<=j<=m)成立. 首先把cij先除到两边去,就变成了l'<=ai/bj<=u',由于差分约束要是的减,怎么变成减法呢?取对数呗,两边取对数得到log(l')<=log(ai)-log(bj)<=l

HDU1534 Schedule Problem 差分约束

囧,还是暴露出了对差分约束理解的不透彻... 一开始根据开始和结束的关系建边,然后建立一个超级源点,连接每一个其他节点,先把这个点入队.本质上相当于把一开始所有的节点都入队了,然后做一遍最长路(最短路,怎么建边的怎么来),相当于把每一个点都作为起点做了一遍最短路,每个点的d取最大的那个. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include &l

HDOJ 1534 Schedule Problem 差分约束

差分约数: 求满足不等式条件的尽量小的值---->求最长路---->a-b>=c----> b->a (c) Schedule Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1503    Accepted Submission(s): 647 Special Judge Problem Descr

HDU-3666 THE MATRIX PROBLEM

很容易发现约束条件:L<=K[i,j]*A[i]/B[j]<=U 妈呀这可是乘法啊...看起来貌似没法化简... 那么看成对数呢? lg(L)<=lg(K[i,j])+lg(A[i])-lg(B[j])<=lg(U) 这样子就能左移右移了吧=v= 判断是否有负权回路即可... #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #includ

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值

hdu 差分约束题集

[HDU]1384 Intervals 基础差分约束★1529 Cashier Employment 神级差分约束★★★★ 1531 King 差分约束★1534 Schedule Problem 差分约束输出一组解★3440 House Man 比较好的差分约束★★3592 World Exhibition 简单★3666 THE MATRIX PROBLEM 中等★★4274 Spy's Work [先处理出欧拉序列,然后就是差分约束了...] [POJ]1201 Intervals1275

Hdu 3666 THE MATRIX PROBLEM(差分约束)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3666 思路:差分约束. 取对数将乘除转化为加减. L<=m[i][j]*a[i]/b[j]<=U log(L/m[i][j])<=log(a[i])-log(b[j])<=log(U/m[i][j]) 则 : log(a[i])<=log(b[j])+log(U/m[i][j]) log(b[j])<=log(a[i])+log(m[i][j]/L) SPFA判