P1511

  1  // 1511 Accepted 196124K 4141MS C++ 4292B PKU
  2 
  3  // 堆优化的邻接链表形式的最短路径
  4  // 注意Heap_Dijkstra( 1, 0 )而不是(1, inn)
  5 
  6  #include  < stdio.h >
  7  #include  < stdlib.h >
  8  #include  < string .h >
  9 
 10 
 11  const   int  size  =   1010010  ;
 12  const   long   long  INF  =   10000000000000  ;
 13 
 14  struct  NODE
 15  {
 16       int  num ;
 17       long   long  len ;
 18       struct  NODE  * next ;
 19 
 20       // NODE() { len = INF ; next = NULL ; }
 21  };
 22  // struct NODE head[size*90] ;
 23  struct  NODE head1[size * 10 ] ;
 24  struct  NODE head2[size * 10 ] ;
 25  int  chead ;
 26 
 27  struct  EDGE
 28  {
 29       int  sn ;  int  en ;  long   long  len ;  int  toheap ;
 30  };
 31  struct  EDGE dist1[size] ;
 32  struct  EDGE dist2[size] ;
 33  // typedef struct EDGE EDGE ;
 34 
 35  int  flag[size] ;
 36  int  heap[size] ;  int  numh ;
 37 
 38  int  inn, inm ;  int  innum ;
 39  long   long   out  ;
 40 
 41  void  input()
 42  {
 43       for int  i = 0 ; i <= inn; i ++  ) head1[i].next  =  head2[i].next  =  NULL ;
 44 
 45       int  sn, en, len ; chead  =  inn  +   10  ;  struct  NODE  * temp ;
 46       for int  i = 1 ; i <= inm; i ++  )
 47      {
 48          scanf(  " %d %d %d " & sn,  & en,  & len ) ;
 49           // data[i][0] = sn ; data[i][1] = en ; data[i][2] = len ;
 50           // temp = (struct NODE *)malloc( sizeof(NODE) ) ;
 51           // struct NODE *temp = new NODE ;
 52          temp  =   & head1[chead ++ ] ;
 53          temp -> len  =  len ; temp -> num  =  en ;
 54          temp -> next  =  head1[sn].next ; head1[sn].next  =  temp ;
 55 
 56           // temp = (struct NODE *)malloc( sizeof(NODE) ) ;
 57          temp  =   & head2[chead ++ ] ;
 58          temp -> len  =  len ; temp -> num  =  sn ;
 59          temp -> next  =  head2[en].next ; head2[en].next  =  temp ;
 60      }
 61  }
 62 
 63  void  swap(  int   & a,  int   & b )
 64  {
 65       int  t  =  a ; a  =  b ; b  =  t ;
 66  }
 67 
 68  void  moveup( EDGE  * arry,  int  n )
 69  { // 将新加入的节点向上移动来维持堆,n表示要向上移动的点的坐标
 70       // while( n && arry[n] > arry[(n-1)>>1] ) // 大顶堆
 71       while ( n && arry[heap[n]].len < arry[heap[(n - 1 ) / 2 ]].len ) // 小顶堆
 72      {
 73          swap( arry[heap[n]].toheap, arry[heap[(n - 1 ) / 2 ]].toheap ) ;
 74          swap( heap[n], heap[(n - 1 ) / 2 ] ) ;
 75          n  =  (n - 1 /   2  ;
 76      }
 77  }
 78 
 79  void  movedown( EDGE  * arry,  int  n )
 80  { // 堆顶改变后,将其向下移动维持堆,n表示堆中元素总数目
 81       int  i  =   0  ;
 82       while ( i + i + 1   <  n )
 83      {
 84           // if( i+i+2<n&&arry[i+i+2]>arry[i+i+1]&&arry[i+i+2]>arry[i] )
 85           if ( i + i + 2 < n && arry[heap[i + i + 2 ]].len < arry[heap[i + i + 1 ]].len && arry[heap[i + i + 2 ]].len < arry[heap[i]].len )
 86          {
 87              swap( arry[heap[i + i + 2 ]].toheap, arry[heap[i]].toheap ) ;
 88              swap( heap[i + i + 2 ], heap[i] ) ;
 89              i  =  i  +  i  +   2  ;
 90          }
 91           // else if( arry[i+i+1] > arry[i] )
 92           else   if ( arry[heap[i + i + 1 ]].len  <  arry[heap[i]].len )
 93          {
 94              swap( arry[heap[i + i + 1 ]].toheap, arry[heap[i]].toheap ) ;
 95              swap( heap[i + i + 1 ], heap[i] ) ; 
 96              i  =  i  +  i  +   1  ;
 97          }
 98           else   break  ;
 99      }
100 
101  }
102 
103  void  Heap_Dijkstra( EDGE dist[], NODE head[],  int  sn,  int  en )
104  {
105      numh  =   - 1  ;  struct  NODE  *  p ;
106       for int  i = 1 ; i <= inn; i ++  )
107      {
108           if ( i  ==  sn )
109          {
110              flag[i]  =   1  ;  // pren[i] = -1 ;
111              dist[i].sn  =  sn ; dist[i].en  =  sn ; dist[i].len  =   0  ;
112              heap[ ++ numh]  =  i ; dist[i].toheap  =  numh ; moveup( dist, numh ) ;
113          }
114           else
115          {
116              flag[i]  =   0  ;  // pren[i] = sn ;
117              dist[i].sn  =  sn ; dist[i].en  =  i ;
118               // for( p=head[sn].next; p!=NULL&&p->num!=i; p=p->next ) ;
119               // if( NULL == p )    dist[i].len = INF ; else dist[i].len = p->len ;
120              dist[i].len  =  INF ;
121              heap[ ++ numh]  =  i ; dist[i].toheap  =  numh ; moveup( dist, numh ) ;
122          }
123      } // init
124       for int  ct = 1 ; ct <= inn; ct ++  )
125      {
126           if ( numh  <   0  )     break  ;
127           int  next  =  dist[heap[ 0 ]].en ;  if ( dist[next].len  >=  INF )     break  ;
128           if ( next  ==  en )     return  ;
129          swap( dist[heap[ 0 ]].toheap, dist[heap[numh]].toheap ) ;
130          swap( heap[ 0 ], heap[numh] ) ; numh --  ; movedown( dist, numh + 1  ) ;
131          flag[next]  =   1  ;  int  curn ; 
132           for ( p = head[next].next; p; p = p -> next )
133          {
134              curn  =  p -> num ;
135               if 0 == flag[curn] && p -> len < INF && dist[next].len + p -> len < dist[curn].len )
136              {
137                  dist[curn].len  =  dist[next].len  +  p -> len ;  // pren[curn] = next ;
138                  moveup( dist, dist[curn].toheap ) ;
139              }
140          }
141      }
142  }
143 
144  void  process()
145  {
146       out   =   0  ;
147 
148      Heap_Dijkstra( dist1, head1,  1 0  ) ;
149       for int  i = 1 ; i <= inn; i ++  )  out   +=  dist1[i].len ;
150 
151      Heap_Dijkstra( dist2, head2,  1 0  ) ; 
152       for int  i = 1 ; i <= inn; i ++  )  out   +=  dist2[i].len ;
153  }
154 
155  void  output()
156  {
157      printf(  " %lld\n " out  ) ;
158  }
159 
160  int  main()
161  {
162       // freopen( "in.txt", "r", stdin ) ;
163       // freopen( "out.txt", "w", stdout ) ;
164 
165       // while( scanf( "%d", &innum ) != EOF )
166      scanf(  " %d " & innum ) ;
167      {
168           for int  ct = 1 ; ct <= innum; ct ++  )
169          {
170              scanf(  " %d %d " , & inn,  & inm ) ;
171 
172                  input() ;
173 
174                  process() ;
175 
176                  output() ;
177          }
178      }
179 
180       return   0  ;
181  }

你可能感兴趣的:(P1511)