• HDU 3666 THE MATRIX PROBLEM


    Description

    You have been given a matrix CNM, each element E of CNM 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 each elements in column-j divided by bj, after this operation every element in this matrix is between L and U, L indicates the lowerbound and U indicates the upperbound of these elements.

    solution

    **正解:差分约束
    化简式子 (L<=a[i][j]*a[i]/b[j]<=U)

    [a[i][j]*a[i]>=L*b[j] ]

    [a[i][j]*a[i]<=U*b[j] ]

    这样子并不好处理,差分约束式子一般表示为 (x+y<z) 的形式,所以想办法转化为加法
    考虑取对数:
    式子就变成了

    [logai-logbj>=logL-loga[i][j] ]

    [logai-logbj<=logU-loga[i][j] ]

    ai到bj分别建边即可**

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #define RG register
    #define il inline
    using namespace std;
    const int N=405,P=805,M=320005,inf=2e8;
    int a[N][N],n,m,U,L,num=0,head[P],to[M],nxt[M],inst[P];
    double dis[M];
    void link(int x,int y,double z){
       nxt[++num]=head[x];to[num]=y;dis[num]=z;head[x]=num;}
    void Clear(){
       memset(head,0,sizeof(head));
       memset(inst,0,sizeof(inst));
       num=0;
    }
    queue<int>q;
    double f[P];int lim;bool vis[P];
    bool spfa(){
       while(!q.empty())q.pop();
       q.push(1);
       for(RG int i=1;i<=n+m;i++)
          vis[i]=0,f[i]=inf;
       RG int x,u;
       f[1]=0;vis[1]=1;inst[1]++;
       while(!q.empty()){
          x=q.front();q.pop();
          for(RG int i=head[x];i;i=nxt[i]){
             u=to[i];
             if(f[x]+dis[i]<f[u]){
                f[u]=f[x]+dis[i];
                if(!vis[u]){
                   vis[u]=1,q.push(u);
                   inst[u]++;
                   if(inst[u]>lim)return 0;
                }
             }
          }
          vis[x]=0;
       }
       return 1;
    }
    void work()
    {
       Clear();
       double lu=log(U),lL=log(L);
       for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++){
             scanf("%d",&a[i][j]);
             link(j+n,i,-lL+log(a[i][j]));
             link(i,j+n,lu-log(a[i][j]));
        }
       lim=sqrt(n+m);
       bool t=spfa();
       if(t)puts("YES");
       else puts("NO");
    }
    
    int main()
    {
    	while(~scanf("%d%d%d%d",&n,&m,&L,&U))
          work();
    	return 0;
    }
    
    
  • 相关阅读:
    c# 在WebBrowser中用SendMessage模拟鼠标点击
    R 脚本读取汇总 Excel 表格数据
    lsyncd —— 多机器实时同步文件神器
    gops —— Go 程序诊断分析工具
    【读书】《跟任何人都聊得来》
    Monkeyrunner自动化测试由浅入深(第一节)
    【读书】《优秀到不能被忽视》
    【管理提升】360管理沟通的学习收获总结
    【读书】《不懂说话你怎么带团队》
    软件测试行业现状 2018年度报告
  • 原文地址:https://www.cnblogs.com/Hxymmm/p/7749717.html
Copyright © 2020-2023  润新知