POJ 1724 优先队列解带限制最短路

这题的实质上是最短路径问题。

大意:从1到N的路程总花费小于等于K的最短路径。

每条路有花费和长度。

依旧采用迪杰斯特拉的贪心思路,每次贪最短的,根据这个点来更新其他的点。

这题我没有注意的是加限制的优先队列的性质:

优先队列的元素保证都是到目标点的花费小于等于K的,这样下来,以长度为第一维度排序的优先队列,第一次到达目标点为终点的时候,此时的len即为所求。

我在这个点坑爹的TLE了。另外由于没有消掉文件读写WA了两次。

#include<iostream>
#include<queue>
#define INF 0x3FFFFFFF
using namespace std;

struct ROADS
{
 	   int v,len,roll;
 	   int next;
 	   ROADS(){
	   		  next=-1;
	   }
}road[22222];

int ptr[111];

struct NODE
{
//public:
 	   int v,len,roll;
 	   friend bool operator <( NODE a,NODE b )
 	   {
		   	  return a.len>b.len;
	   }
	   NODE( int a=0,int b=0,int c=0 ){
	   		 v=a;len=b;roll=c;
	   }
};
int Ecnt;

void addEdge( int u,int v,int len,int roll )
{
 	 road[Ecnt].v=v;
 	 road[Ecnt].len=len;
 	 road[Ecnt].roll=roll;
 	 road[Ecnt].next=ptr[u];
 	 ptr[u]=Ecnt++;
}

int main()
{
 	//freopen( "test.in","r",stdin );
 	//freopen( "ans.out","w",stdout );
 	int K,N,R;
 	while( scanf("%d %d %d",&K,&N,&R )!=EOF )
 	{
	 	   memset( ptr,-1,sizeof(ptr) );
	 	   Ecnt=0;
	 	   int u,v,len,roll;
	 	   for( int i=0;i<R;i++ )
	 	   {
		   		scanf( "%d %d %d %d",&u,&v,&len,&roll );
		   		addEdge( u,v,len,roll );
		   		//addEdge( v,u,len,roll );
		   }
		   priority_queue<NODE> PQ;
		   NODE temp(1,0,0);
		   PQ.push(temp);
 		   int ans=-1;
		   while( !PQ.empty() )//按dijstra每次取出最短的 
		   {
		   		  NODE cur=PQ.top();
 	   	   		  PQ.pop();
		   		  if( cur.v==N )
		   		  {
				   	  ans=cur.len;
				   	  break;
			  	  }
		   		  for( int i=ptr[cur.v];i!=-1;i=road[i].next )
		   		  {
				   	   if( cur.roll+road[i].roll<=K )
				   	   {
					   	   temp.v=road[i].v;
					   	   temp.len=cur.len+road[i].len;
					   	   temp.roll=cur.roll+road[i].roll;
					   	   PQ.push(temp);
					   }
 	   	   		  }
 		   }
  		   printf( "%d\n",ans );
  	}
 	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值