hdu 3666 THE MATRIX PROBLEM (差分约束)

http://acm.hdu.edu.cn/showproblem.php?pid=3666

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

题解: 差分约束。

  首先   L<= c[i][j] *ai / bj  <= u ,以前 我们遇到的都是 减法的  差分约束  ,那么我们 只i要  取  log  就可以 了,两边 他同除以 c[i][j] ,  然后取 log  锝 ,log(l) - log(c[i][j]) <= log(a) - log(b) <= log(u) - log(c[i][j]) ;  然后 SPFA  判断一下 是否 有  负环 即可。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include<string>
 11 #define Min(a,b) a<b?a:b
 12 #define Max(a,b) a>b?a:b
 13 #define CL(a,num) memset(a,num,sizeof(a));
 14 #define eps  1e-6
 15 #define inf 10001000
 16 
 17 #define ll   __int64
 18 
 19 #define  read()  freopen("data.txt","r",stdin) ;
 20 #define inf  9999999
 21 using namespace std;
 22 
 23 const double pi  = acos(-1.0);
 24 const int maxn = 210;
 25 #define N 1000
 26 
 27 
 28  int n,m,vis[N],num,head[N];
 29  int time[N];//记录入队列的次数
 30  int s,t ;
 31  double dis[N] ;
 32  struct node
 33  {
 34      int next;
 35      int v;
 36      double w;
 37  }p[N*N];
 38 
 39 queue<int>que;
 40  void add(int u,int v,double w)
 41  {
 42 
 43      p[num].v=v;
 44      p[num].w=w;
 45      p[num].next=head[u];
 46      head[u]=num;
 47      num++;
 48  }
 49 
 50  int SPFA()
 51  {
 52 
 53      memset(vis,0,sizeof(vis));
 54      CL(time,0)  ;
 55      for(int i=0;i<=t;i++)dis[i]= inf;
 56 
 57      dis[s] = 0;
 58 
 59      while(!que.empty())que.pop();
 60      que.push(s) ;
 61      vis[s] = 1 ;
 62 
 63      while(!que.empty())
 64      {
 65          int u=que.front();
 66          vis[u]=0;
 67          que.pop();
 68          for(int i=head[u];i!=-1;i=p[i].next)
 69          {
 70              int v=p[i].v;
 71              double w=p[i].w;
 72              if(dis[v] > dis[u] + w)
 73              {
 74                  dis[v] = dis[u]+w;
 75                  if(!vis[v])
 76                  {
 77                      vis[v]=1;
 78                      que.push(v);
 79                      time[v]++;
 80                      if(time[v]>(int)sqrt(t*1.0))return -1;// 含有回路
 81                  }
 82              }
 83          }
 84      }
 85      return 1;
 86 
 87  }
 88 
 89  int main()
 90  {
 91      int i , j , x,y,d,mx,a,b,mi,l,u;
 92      double c ;
 93      while(scanf("%d%d%d%d",&n,&m,&l,&u)!=EOF)
 94      {
 95          num  = 0 ;
 96          CL(head, -1) ;
 97          double  l1 = log(l*1.0) ;
 98          double  u1 = log(u*1.0) ;
 99          for(i = 1; i <= n;i++)
100          {
101              for(j = 1 ; j <= m;j++)
102              {
103                  scanf("%lf",&c) ;
104                  double a = log(c);
105 
106                  add(i,j + n,a - l1);
107                  add(j + n,i ,u1 - a) ;
108 
109              }
110          }
111          s = 1;
112          t = m + n ;//因为 他图是联通的 所以 不用 加入  源点 ;
113 
114          int f = SPFA();
115          if(f == 1)puts("YES");
116          else puts("NO") ;
117 
118 
119 
120      }
121 
122  }

 

原文地址:https://www.cnblogs.com/acSzz/p/2728073.html