POJ 1724 - ROADS 有限制的最短路,A*

    题意:

               在一个有向图中,每条边对应有其有长度和过路费,现在手握K元..要从1点走向N点...问过路费总和不大于K的最短路径长度是多少.

    题解:  

               首先要注意几个细节:    1、题目给出的是有向图

                                                    2、两点间可能存在多条边

                                                    3、可能存在环

                                                    4、可能N点不可达

              解决方法应该挺多的...我就用A*水了..和找K短路没多大区别...注意保持当前路径的费用不大于自己有的钱就ok了~


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#define ll long long
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 105
using namespace std;  
struct node
{
       int x,toll,g,h;
       bool operator <(node a) const
       {
              return a.g+a.h<g+h;
       }
}; 
struct LINE
{
       int y,t,l,next;
}line[MAXN*MAXN],line1[MAXN*MAXN];
int K,N,dis[MAXN],num[MAXN],_next[MAXN],_next1[MAXN];
priority_queue<node> Astarqueue; 
queue<int> SPFAqueue;
bool inqueue[MAXN]; 
void addline(int x,int y,int l,int t,int m)
{
       line[m].next=_next[x], _next[x]=m;
       line[m].y=y,line[m].l=l,line[m].t=t;
} 
void addline1(int x,int y,int l,int t,int m)
{
       line1[m].next=_next1[x], _next1[x]=m;
       line1[m].y=y,line1[m].l=l,line1[m].t=t;
} 
void SPFA()
{
       int h,k;
       memset(inqueue,false,sizeof(inqueue));
       while (!SPFAqueue.empty()) SPFAqueue.pop();
       memset(dis,-1,sizeof(dis));
       SPFAqueue.push(N);
       dis[N]=0;
       while (!SPFAqueue.empty())
       {
              h=SPFAqueue.front();
              SPFAqueue.pop();
              inqueue[h]=false;
              k=_next1[h];
              while (k)
              {
                      if (dis[line1[k].y]==-1 || dis[line1[k].y]>line1[k].l+dis[h]) 
                      {  
                             dis[line1[k].y]=line1[k].l+dis[h];
                             if (!inqueue[line1[k].y])
                             {
                                  inqueue[line1[k].y]=true;
                                  SPFAqueue.push(line1[k].y);
                             }
                      }     
                      k=line1[k].next;  
              }
       }
       return;      
}
int Astar()
{ 
       int k;
       node h,p;
       while (!Astarqueue.empty()) Astarqueue.pop(); 
       memset(num,0,sizeof(num));
       h.x=1,h.g=0,h.h=dis[h.x],h.toll=0;
       Astarqueue.push(h);
       while (!Astarqueue.empty())
       {
               h=Astarqueue.top();
               Astarqueue.pop();
               if (h.x==N) break;
               num[h.x]++;
               if (num[h.x]>2*N) break;
               k=_next[h.x]; 
               while (k)
               {
                      if (dis[line[k].y]!=-1 && line[k].t+h.toll<=K)
                      { 
                             p.toll=line[k].t+h.toll;
                             p.x=line[k].y,p.h=dis[p.x],p.g=h.g+line[k].l;  
                             Astarqueue.push(p);
                      }
                      k=line[k].next;
               }  
       }
       if (h.x!=N) return -1;
       return h.g;
}
int main()
{  
       int M,i,num;  
       scanf("%d%d%d",&K,&N,&M); 
       memset(_next,0,sizeof(_next));
       memset(_next1,0,sizeof(_next1));
       num=0;
       while (M--)
       {
               int s,d,l,t; 
               scanf("%d%d%d%d",&s,&d,&l,&t);
               addline(s,d,l,t,++num); 
               addline1(d,s,l,t,num);
       } 
       SPFA();
       printf("%d\n",Astar());
       return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值