• 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;
    }
  • 相关阅读:
    黑马程序员_java基础笔记(13)...类加载器和代理
    nyoj-411-Friends number
    nyoj-38-布线问题
    nyoj-233-Sort it
    nyoj-115-城市平乱
    nyoj-608-畅通工程
    nyoj-36-最长公共子序列
    nyoj-150-Train Problem I
    nyoj-494-Dancing With the Googlers
    nyoj-214-单调递增子序列(二)
  • 原文地址:https://www.cnblogs.com/BruceNoOne/p/3253927.html
Copyright © 2020-2023  润新知