hdu3666差分约束

第一次做差分约束。

题意:给你一个N*M的矩阵,求两列数a1,a2,a3...an 和 b1,b2.....bm使得对矩阵中的每个数进行下面的操作之后的值在[L,U]之间,

操作为:a[i] * m[i][j] / b[j]。  N,M<=400

转:思路:差分约束。由题意可知,对于矩阵中的每个元素要满足的条件是:L <= a[i] * m[i][j] / b[j] <= U ,这样我们就可以得到下面的两个式子:L*b[j] <= a[i]  * m[i][j]  和 a[i] * m[i][j]  <= U*b[j] ,因为差分约束中dis[]前面没有系数,为了把系数取消掉,我们可以用对式子两遍取对数,就可以得到:log(b[j]) - log( a[i] ) <= log( m[i][j] / L) ,同理可以得到两个式子,最后用spfa判负环就可以得出答案了。

差分约束最难得是怎么建立三角不等式。

代码:

#include <iostream>
#include <cmath>
#include<queue>
using namespace std;
const int N=1000;
const int M=500000;
const int inf=1<<30;
int vis[N],head[N],in[N];
struct node
{
    int v,next;
    double w;
}e[M];
int tot,n,m;
double dis[N];
void add(int a,int b,double w)
{
    e[tot].v=b;
    e[tot].w=w;
    e[tot].next=head[a];
    head[a]=tot++;
}
bool spfa()
{
    int i;
    queue<int>q;
    for(i=0;i<=n;i++)
    {
        dis[i]=inf;
        vis[i]=0;
        in[i]=0;
    }
    dis[1]=0;
    vis[1]=1;
    in[1]=1;
    q.push(1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(i=head[u];i+1;i=e[i].next)
        {
            int v=e[i].v;
            double w=dis[u]+e[i].w;
            if(dis[v]>w)
            {
                dis[v]=w;
                if(!vis[v])
                {
                    
                    vis[v]=1;
                    if(++in[v]>(int)sqrt(n*1.0))return false;//如果是判断n次就会超时,一般每个点入队的次数不会很多,所有的入队次数大概是T*n,T大概是2左右
                    q.push(v);
                }
            }
        }
        
    }
    return true;
}
int main()
{
    int i,l,u;
    while(scanf("%d%d%d%d",&n,&m,&l,&u)!=EOF)
    {
        double L,U,map;
        L=log(l*1.0);
        U=log(u*1.0);
        memset(head,-1,sizeof(head));
        tot=0;
        for(i=1;i<=n;i++)
        {
            for (int j=1;j<=m;j++)
            {
                scanf("%lf",&map);
                map=log(map);
                add(i,j+n,map-L);
                add(n+j,i,U-map);
            }
        }
        n=n+m;
        if(spfa())
            printf("YES
");
        else
            printf("NO
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/BruceNoOne/p/3253927.html