最短路径- URI在线判断1640

Shortest-Path - URI Online Judge 1640

本文关键字:判断 1640 在线 URI 最短路径      更新时间:2023-10-16

我试图通过这个代码在uri在线判断,但我不知道我的错误在哪里,所有的测试我做的工作。

链接问题是这样的:https://www.urionlinejudge.com.br/repository/UOJ_1640_en.html

问题描述如下:

运输公司经常需要将货物从一个城市运送到另一个城市。这家运输公司与一家连锁酒店达成了一项特殊协议,允许其司机免费入住该连锁酒店。司机每天最多只能开车10个小时。运输公司想要找到一条从出发城市到目的地城市的路线,使得司机总是可以在连锁酒店中的一家酒店过夜,并且从一家酒店到下一家酒店(或目的地)最多需要开车10个小时。当然,交货所需的天数也应该尽量减少。输入

输入文件包含几个测试用例。每个测试用例以包含整数n(2≤n≤10000)的行开头,n是规划路由时需要考虑的城市数目。为简单起见,城市编号从1到n,其中1是起始城市,n是目的地城市。下一行包含一个整数h,后面跟着数字c1, c2,…, ch表示该连锁酒店所在城市的数量。可以假设0≤h≤min(n, 100)。每个测试用例的第三行包含一个整数m(1≤m≤105),表示规划路径时需要考虑的道路数。下面的m条线描述了道路。每条道路用一条包含3个整数a, b, t(1≤a, b≤n, 1≤t≤600)的直线来描述,其中a, b为道路连接的两个城市,t为驾驶员从道路一端开车到另一端所需的时间,单位为分钟。输入以n = 0终止。输出

对于每个测试用例,打印一行包含从城市1到城市n的运输公司必须预订的最少酒店数量。如果不可能找到司机每天最多开车10小时的路线,则打印-1。

和我的尝试解决方案是在我的github:https://github.com/h31nr1ch/uri/blob/master/1640.cpp

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <limits> // for numeric_limits
#include <set>
#include <utility> // for pair
#include <algorithm>
#include <iterator>
using namespace std;
typedef long long int vertex_t;
typedef double weight_t;
const weight_t max_weight = numeric_limits<double>::infinity();
struct neighbor {
  vertex_t target;
  weight_t weight;
  weight_t current;
  bool hotel;
  neighbor(vertex_t arg_target, weight_t arg_weight,weight_t arg_current,bool arg_hotel):target(arg_target), weight(arg_weight),current(arg_current),hotel(arg_hotel){ }
};
typedef vector<vector<neighbor> > adjacency_list_t;
void DijkstraComputePaths(vertex_t source,adjacency_list_t &adjacency_list, vector<weight_t> &min_distance, vector<vertex_t> &previous,vector<vertex_t> &hoteis,vector<vertex_t> &weights,vector<bool> &tHotel){
  int n = adjacency_list.size();
  min_distance.clear();
  min_distance.resize(n, max_weight);
  min_distance[source] = 0;
  previous.clear();
  previous.resize(n, -1);
  weights.clear();
  weights.resize(n,0);
  tHotel.clear();
  tHotel.resize(n,false);
  set<pair<weight_t, vertex_t> > vertex_queue;
  vertex_queue.insert(make_pair(min_distance[source], source));
  while (!vertex_queue.empty()){
    weight_t dist = vertex_queue.begin()->first;
    vertex_t u = vertex_queue.begin()->second;
    vertex_queue.erase(vertex_queue.begin());
    vector<neighbor> &neighbors = adjacency_list[u];
    for (vector<neighbor>::iterator neighbor_iter = neighbors.begin(); neighbor_iter != neighbors.end(); neighbor_iter++){
      vertex_t v = neighbor_iter->target;
      weight_t weight = neighbor_iter->weight;
      weight_t current= neighbor_iter->current;
      weight_t distance_through_u = dist + weight;
      if (distance_through_u < min_distance[v]) {
        bool l=true;
        bool ho=false;//Variavel criada para falar se dormiu no hotel ou nao
        //if(distance_through_u>600){
        if(weight+weights[u]>600){
          //Procurando por um hotel
          if(hoteis.size()==0)
            l=false;
          for(vector<vertex_t>::iterator it=hoteis.begin();it!=hoteis.end();it++){
            if(*it==u){
              l=true;
              ho=true;
              break;
            }
            else{
              l=false;
            }
          }
        }
        if(l){
          if(ho){
            tHotel[v]=true;
            weights[v]=weight;
            //cout<<"O nó u= "<<u<<" e nó v= "<<v<<" precisaram de hotel! Entao o peso é: "<<weights[v]<<endl;
          }
          else{
            tHotel[v]=false;
            weights[v]=distance_through_u;
            //cout<<"O nó u= "<<u<<" e nó v= "<<v<<" NÃO precisaram de hotel! Entao o peso é: "<<weights[v]<<endl;
          }
          vertex_queue.erase(make_pair(min_distance[v], v));
          min_distance[v] = distance_through_u;
          previous[v] = u;
          vertex_queue.insert(make_pair(min_distance[v], v));
        }
      }
    }
  }
}
list<vertex_t> DijkstraGetShortestPathTo( vertex_t vertex, const vector<vertex_t> &previous){
   list<vertex_t> path;
   for (;vertex != -1; vertex = previous[vertex])
     path.push_front(vertex);
   return path;
}
int main(){
  int n=1,m,x,y,w,v;
  while(n!=0){
    vector<vertex_t> hoteis;
    cin>>n;
    adjacency_list_t adjacency_list(n);
    if(n==0)
      break;
    cin>>v;
    for(int i=0;i<v;i++){
      cin>>x;
      hoteis.push_back(x-1);
    }
    cin>>m;
    for(int i=0;i<m;i++){
      cin>>x>>y>>w;
      adjacency_list[x-1].push_back(neighbor(y-1,w,0,false));
    }
    vector<weight_t> min_distance;
    vector<vertex_t> previous;
    vector<vertex_t> weights;
    vector<bool> tHotel;
    DijkstraComputePaths(0, adjacency_list, min_distance, previous,hoteis,weights,tHotel);
    //cout << "Distance from 0 to "<<n-1<<" : " << min_distance[n-1] << endl;
    list<vertex_t> path = DijkstraGetShortestPathTo(n-1, previous);
    //cout<<"Weights: ";
    //copy(min_distance.begin(),min_distance.end(),ostream_iterator<vertex_t>(cout," "));
    //cout<<endl;
    //cout << "Path : ";
    //copy(path.begin(), path.end(), ostream_iterator<vertex_t>(cout, " "));
    //cout<<endl;
    int total=0;
    //for(vector<bool>::iterator it=tHotel.begin();it!=tHotel.end();it++){
    //  cout<<*it<<" ";
    //}
    for(list<vertex_t>::iterator it=path.begin();it!=path.end();it++){
      if(tHotel[*it]==1)
        total++;
    }
    //cout<<endl;
    if(min_distance[n-1]==max_weight){
      cout<<"-1n";
    }
    else{
      cout<<total<<endl;
    }
  }
  return 0;
}

感谢您的帮助

这个问题可以通过首先计算酒店之间的最小旅行时间来简化。这意味着你从每个酒店计算,通过道路到达其他酒店所需的最短时间。

然后,计算城市1到每家酒店的最短距离,同理,计算城市n到每家酒店的最短距离。

使用新的距离,用酒店和其他2个城市之间的最短路径形成一个新的图。如果路径长度为>600,则忽略它(这意味着不要将其放入新图中)。然后使用Dijkstra,每条边的权重为1。这将告诉你到达目的地所需的最少酒店数量+ 1。如果新图中没有路径,则不可能。

算法将取O((k+2)m log n + m log (k+2)) = O(km log n)