HDU 3499 Flight spfa+dp

自认为相当正确的代码,交上去TLE了。以为是自己的方法错了,从昨晚开始想,到底错哪了?昨晚上看到了熟人的代码,依然大牛。网上的解法大多是正反向最短路+枚举折半边。这样得出。但是我的代码是:用dist[x][0]记录到x点使用折半票的花费,dist[x][1]记录到x点全票的花费。这样dp方程就很容易出来了... 自己想吧。

今天下午改了改,发现这题光读入数据就要3600ms++,最终发现是我的spfa速度慢了。再继续追下去,发现是我的spfa用的数据结构不对,我用的栈,人家ac的用的队列。我的发现总结一下吧:

1.spfa用队列比用栈快,特别是在边很多的情况。

2.用STL的队列和栈的速度比自己实现的栈速度快。

3.dist[10000][2]>dist1[10000]+dist2[10000]>dist[2][10000],读取速度依次减少。

终于还是让哥给切掉了! 哇卡卡卡!

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#define MAXN 111111
#define MAXM 555555
const __int64 INF=(_I64_MAX)>>1;
//const __int64 INF=4611686018427387903;
using namespace std;

struct node
{
 	   int v;
	   __int64 price;
 	   node* next;
}Edge[MAXM],*ptr[MAXN];

int EdgeNum;
int N,M;//N node,M edge
 	
void addEdge( int u,int v,__int64 price )
{
 	 node *p=&Edge[EdgeNum++];
 	 p->price=price;
 	 p->v=v;
 	 p->next=ptr[u];
 	 ptr[u]=p;
}

__int64 dist[2][MAXN];
bool inS[MAXN];

__int64 spfa( int src,int dst )
{
 	 for( int i=0;i<=N;i++ )
 	 {
 	 	  dist[1][i]=dist[0][i]=INF;
 	 	  inS[i]=false;
	 }
 	 queue<int>myQ;
 	 dist[1][src]=dist[0][src]=0;
 	 
	 int top=0;
	 myQ.push(src);
 	 inS[src]=true;
 	 
 	 while( !myQ.empty() )
 	 {
	  		int cur=myQ.front();
	  		myQ.pop();
	  		node *p=ptr[cur];
	  		while( p )
	  		{
			 	   bool flag=false;
			 	   if( dist[1][p->v]>dist[1][cur]+p->price )
			 	   	   dist[1][p->v]=dist[1][cur]+p->price,flag=true;
			 	   	   
			 	   if( dist[0][p->v]>dist[0][cur]+p->price ||  dist[0][p->v]>dist[1][cur]+p->price/2 )
					   dist[0][p->v]=min( dist[0][cur]+p->price,dist[1][cur]+p->price/2 ),flag=true;
				   
				   if( flag && inS[p->v]==false )
	   	   		   {
	   	   		   	   myQ.push(p->v);
		   	   	   	   inS[p->v]=true;
  	   			   }
			 	   p=p->next;
 	   		}
	  		inS[cur]=false;
	 }
	 return dist[0][dst];
}

string str1,str2;

int main()
{
 	while( scanf( "%d %d",&N,&M )!=EOF )
 	{
	 	   memset( ptr,0,sizeof(ptr) );
	 	   EdgeNum=0;
		   map<string,int>map;
 	 	   int citynum=1;
		   __int64 price;
		   //cout<<INF<<endl;
   	   	   map.clear();
   	   	   
		   for( int i=1;i<=M;i++ )
		   {
		   		cin>>str1>>str2>>price;
		   		if( map.find(str1)==map.end() )
		   			map[str1]=citynum++;
		   		if( map.find(str2)==map.end() )
		   			map[str2]=citynum++;
		   		addEdge( map[str1],map[str2],price );
   		   }
	 	   cin>>str1>>str2;
	 	   //若SE城市中没有可去的边 
	 	   if( map.find(str1)==map.end() || map.find(str2)==map.end() )
	 	   {
	 	   	   printf("-1\n"); continue;
		   }
		   //S==E
		   else if( str1==str2 )
		   {
	 	   	    printf("0\n"); continue;
   		   }
   		   
	 	   __int64 ans=spfa( map[str1],map[str2] );
	 	   
		   if( ans==INF )
           	   printf("-1\n");
		   else
           	   printf("%I64d\n",ans);
  	}
  	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值