UVA11367 最短路 蓝书练习题

题意:n个城市,m条无向边,每个城市油价不一样。q次询问,给定起点s,终点e,求问最便宜路径。 油箱一开始设为0,假设每单位距离消耗1L汽油。


分析:dijkstra变形,设d[u][fuel] 表示到达城市u剩余油量为fuel的最小花费代价。这里很多状态是无用的,不需要全部求出来,每次加油一升一升的加。


代码如下:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

const int INF = 1e9;
const int maxn = 1000+10;
int p[maxn];
int n,m,tot;
struct Edge{
   int from,to,dist;
};
vector<Edge>edges;
vector<int>G[maxn];
int q,s,e,c;

inline void add_edge(int u, int v, int d){
   edges.push_back((Edge){u,v,d});
   tot = edges.size() - 1;
   G[u].push_back(tot);
}

void Read(){
   scanf("%d %d",&n,&m);
   for (int i=0; i<n; i++) scanf("%d",&p[i]);
   for (int i=0; i<=n; i++) G[i].clear();
   edges.clear();
   tot = 0;

   int u,v,d;
   for (int i=1; i<=m; i++) {
        scanf("%d %d %d",&u,&v,&d);
        add_edge(u,v,d);
        add_edge(v,u,d);
   }
}

int d[maxn][100+5];
struct HeapNode{
   int cost,f,u;
   bool operator <(const HeapNode &rhs) const {
       return cost > rhs.cost;
   }
};
priority_queue<HeapNode>que;

int dijkstra(int s,int t, int c){
   memset(d,-1,sizeof(d));
   while (!que.empty()) que.pop();
   que.push((HeapNode){0,0,s});

   HeapNode x,Q;
   Edge e;
   int u,v,tmp;

   while (!que.empty()){
      x = que.top(); que.pop(); u = x.u;
      if (u == t) return x.cost;
      for (int i=0; i<G[u].size(); i++) {
           e = edges[G[u][i]];
           if (e.dist > c) continue;
           if (x.f >= e.dist) {
              tmp = x.f - e.dist;
              if (d[e.to][tmp] == -1 || d[e.to][tmp] > x.cost) {
                   d[e.to][tmp] = x.cost;
                   Q.u = e.to;
                   Q.cost = x.cost;
                   Q.f = tmp;
                   que.push(Q);
              }
           }

           if (x.f < c) {
              if (d[x.u][x.f+1] == -1 || d[x.u][x.f+1]>d[x.u][x.f]+p[u]){
                  d[x.u][x.f+1] = d[x.u][x.f] + p[u];
                  Q.f = x.f+1;
                  Q.u = x.u;
                  Q.cost = x.cost + p[u];
                  que.push(Q);
              }
           }
      }
   }
   return -1;
}

int main(){
    Read();
    scanf("%d",&q);
    while (q--){
       scanf("%d %d %d",&c,&s,&e);
       int ans =  dijkstra(s,e,c);
       if (ans == -1) printf("impossible\n"); else printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值