UVa 11635 - Hotel booking

来源:互联网 发布:insar数据 编辑:程序博客网 时间:2024/04/30 17:15

题目:求从起点到终点住过的hotel最少次数。

分析:最短路、优先队列。利用spfa和优先队列求解。如果不用优先队列,则有n*h*t种状态,定会TLE,因此利用优先队列并利用优先队列的性质加以优化。优先队列元素的权值为二元组<hotel,time>分别代表住过的Hotel数和从Hotel或起点出发后走到当前节点所有的时间。其中hotel的优先级高,所以程序是按照hotel递增的顺序运行的,和bfs时扫描的节点是相邻层的一样。因此,每次找到新的节点时:1.如果和上次找到它时的hotel相同,则只有time少于上次才会进入优先队列;2.如果hotel增加则置上次的time为max。利用数组sleep和times记录上次找到此节点时的hotel和time。

注意:hotel不一定必须住;已经入住过的旅馆不再住,避免增加计算量。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;int hotel[ 10005 ];//是否是hotelint times[ 10005 ];//上次找到此节点时的timeint Sleep[ 10005 ];//上次找到此节点时的hoteltypedef struct dnode{int id;int hotel;int time;dnode( int i, int h, int t) {id = i;hotel = h;time = t;}dnode(){}}dnode;int cmp( dnode a, dnode b ){if ( a.hotel == b.hotel )return a.time - b.time;return a.hotel - b.hotel;}typedef struct lnode{int    time;int    point;lnode* next;}lnode;lnode* head[ 10005 ];lnode  edge[ 200005 ];int    e_count = 0;void addlist( int a, int b, int t ){edge[ e_count ].next  = head[ a ];edge[ e_count ].point = b;edge[ e_count ].time  = t;head[ a ] = &edge[ e_count ++ ];}class heap{private:int   size;dnode *data;public:heap() {size = 0;data = new dnode[ 20005 ];//每个点最多入队2次 memset( data, 0, sizeof( data ) );}~heap() { delete [] data; }int empty(){ return size == 0; }void Insert( dnode node ) {data[ ++ size ] = node;int now = size;while ( now > 1 && cmp( data[ now ], data[ now>>1 ] ) < 0 ) {swap( data[ now ], data[ now>>1 ] );now = now>>1;}}dnode Delete() {swap( data[ 1 ], data[ size ] );int now = 1;while ( 1 ) {int New = now,L = now<<1,R = (now<<1)+1;if ( L < size && cmp( data[ L ], data[ New ] ) < 0 ) New = L;if ( R < size && cmp( data[ R ], data[ New ] ) < 0 ) New = R;if ( New == now ) break;swap( data[ New ], data[ now ] );now = New;}return data[ size -- ];}};int spfa( int s, int e, int n ){for ( int i = 1 ; i <= n ; ++ i ) {Sleep[ i ] = -1;times[ i ] = -1;}heap Heap;Heap.Insert( dnode(s,0,0) );while ( !Heap.empty() ) {dnode now = Heap.Delete();if ( now.id == e ) return now.hotel;for ( lnode* p = head[ now.id ] ; p ; p = p->next ) {int t = now.time + p->time;if ( Sleep[ p->point ] < now.hotel ) {Sleep[ p->point ] = now.hotel;times[ p->point ] = 601;}if ( times[ p->point ] > t && hotel[ p->point ] ) {//不是已找到的旅馆times[ p->point ] = t;Heap.Insert( dnode(p->point,now.hotel,t) );if ( hotel[ p->point ] == 1 ) {hotel[ p->point ] = 0;Heap.Insert( dnode(p->point,now.hotel+1,0) );}}}}return -1;}int main(){int n,h,c,m,a,b,t; while ( scanf("%d",&n) && n ) {scanf("%d",&h);memset( hotel, -1, sizeof( hotel ) );for ( int i = 1 ; i <= h ; ++ i ) {scanf("%d",&c);hotel[ c ] = 1;}memset( head, 0, sizeof( head ) );e_count = 0;scanf("%d",&m);for ( int i = 1 ; i <= m ; ++ i ) {scanf("%d%d%d",&a,&b,&t);addlist( a, b, t );addlist( b, a, t );}printf("%d\n",spfa( 1, n, n ));}return 0;}


原创粉丝点击