HDU 3666 THE MATRIX PROBLEM

HDU 3666 THE MATRIX PROBLEM

/*
 * File:   HDU 3666 THE MATRIX PROBLEM
 * Author: xiaotian @ hnu
 * Created on 2010年9月30日, 下午12:28
 * 题解:哈尔滨现场赛G题,看到题目想到是差分约束,但是一时没想出怎么建图
 * 贺神说log下不就可以很容易的建图了,于是被点化。
 * 建图还是比较裸的。直接spfa跑一下有负环就不可行,否则可行。
 * 刚开始谢了一个版本TLE了,原因是 cnt[V[e]] > sqrt(1.0 * n) 就可以直接判断了,我却要等到它大于 n 。
 * 写了两个版本的,第一个版本是链表实现的,发现速度很慢,1900+ms,时间上有点擦边。
 * 又写了一个数组版本的,速度相对快一点,大约能降到 1000+ms 。
 */

版本一:
 1  #include < stdio.h >
 2  #include < string .h >
 3  #include < queue >
 4  #include < math.h >
 5  #include < algorithm >
 6  using   namespace  std;
 7  #define  N 408
 8  #define  inf 0x3fffffff
 9  int  n, m, ne;
10  double  low, hig;
11  int  vis[ 2   *  N], num[ 2   *  N];
12  double  d[ 2   *  N];
13 
14  struct  node {
15       int  adj;
16       double  w;
17      node  * next;
18  * head[ 2   *  N], g[ 2   *  N  *  N];
19 
20  void  addedge( int  x,  int  y,  double  w) {
21      g[ne].adj  =  y;
22      g[ne].w  =  w;
23      g[ne].next  =  head[x];
24      head[x]  =   & g[ne];
25      ne ++ ;
26  }
27 
28  void  build() {
29      memset(head,  0 sizeof  (head));
30      ne  =   0 ;
31       double  a  =  log(hig);
32       double  b  =  log(low);
33       for  ( int  i  =   0 ; i  <  n; i ++ )
34           for  ( int  j  =   0 ; j  <  m; j ++ ) {
35               double  c;
36              scanf( " %lf " & c);
37              c  =  log(c);
38              addedge(i  +   1 , j  +  n  +   1 , a  -  c);
39              addedge(j  +  n  +   1 , i  +   1 , c  -  b);
40          }
41  }
42 
43  int  solve() {
44       int  i;
45      queue < int >  q;
46       for  (i  =   1 ; i  <=  n; i ++ ) {
47          q.push(i);
48          d[i]  =  inf;
49          vis[i]  =   1 ;
50          num[i]  =   0 ;
51      }
52       while  ( ! q.empty()) {
53           int  x  =  q.front();
54          q.pop();
55          vis[x]  =   0 ;
56           for  (node  * =  head[x]; p; p  =  p -> next)
57               if  (d[p -> adj]  >  d[x]  +  p -> w) {
58                  d[p -> adj]  =  d[x]  +  p -> w;
59                   if  ( ! vis[p -> adj]) {
60                      vis[p -> adj]  =   1 ;
61                      num[p -> adj] ++ ;
62                       if  (num[p -> adj]  >=  ( int ) sqrt( 1.0   *  n))  return   0 ;
63                      q.push(p -> adj);
64                  }
65              }
66      }
67       return   1 ;
68  }
69 
70  int  main() {
71       while  (scanf( " %d %d %lf %lf " & n,  & m,  & low,  & hig)  !=  EOF) {
72          build();
73          n  +=  m;
74           int  ans  =  solve();
75          puts(ans  ?   " YES "  :  " NO " );
76      }
77       return   0 ;
78  }

版本二 :
 1  #include < iostream >
 2  #include < cmath >
 3  #include < queue >
 4  #define  N 810
 5  #define  E 320010
 6  using   namespace  std;
 7 
 8  bool  vis[N];
 9  int  cnt[N];
10  double  dis[N];
11  int  head[N];
12  int  V[E], next[E];
13  double  W[E];
14  int  ne, n, m;
15 
16  void  addedge( int  u,  int  v,  double  w) {
17      V[ne]  =  v;
18      W[ne]  =  w;
19      next[ne]  =  head[u];
20      head[u]  =  ne ++ ;
21  }
22 
23  void  build( double  l,  double  r) {
24      ne  =   0 ;
25      l  =  log(l);
26      r  =  log(r);
27      memset(head,  - 1 sizeof  (head));
28       for  ( int  i  =   0 ; i  <  n; i ++ )
29           for  ( int  j  =   0 ; j  <  m; j ++ ) {
30               int  a;
31              scanf( " %d " & a);
32               double  c  =  log(a);
33              addedge(j  +  n, i, r  -  c);
34              addedge(i, j  +  n, c  -  l);
35          }
36      n  +=  m;
37  }
38 
39  bool  spfa() {
40       int  i;
41      queue < int > q;
42       for  (i  =   0 ; i  <  n; i ++ ) {
43          vis[i]  =   true ;
44          dis[i]  =   10000000 ;
45          q.push(i);
46          cnt[i]  =   0 ;
47      }
48      dis[ 0 =   0 ;
49       while  ( ! q.empty()) {
50           int  u  =  q.front();
51          q.pop();
52          vis[u]  =   0 ;
53           for  ( int  e  =  head[u]; e  !=   - 1 ; e  =  next[e]) {
54               if  (dis[u]  +  W[e]  <  dis[V[e]]) {
55                  dis[V[e]]  =  dis[u]  +  W[e];
56                   if  ( ! vis[V[e]]) {
57                      q.push(V[e]);
58                      vis[V[e]]  =   1 ;
59                       if  ( ++ cnt[V[e]]  >  ( int ) sqrt( 1.0   *  n))
60                           return   0 ;
61                  }
62              }
63          }
64      }
65       return   1 ;
66  }
67 
68  int  main() {
69       double  l, r;
70       while  (scanf( " %d%d%lf%lf " & n,  & m,  & l,  & r)  !=  EOF) {
71          build(l, r);
72          puts(spfa()  ?   " YES "  :  " NO " );
73      }
74       return   0 ;
75  }


你可能感兴趣的:(HDU 3666 THE MATRIX PROBLEM)