General
 
 
# Author Problem Lang Verdict Time Memory Sent Judged  
256992348 Practice:
batubb
449B - 29 C++17 (GCC 7-32) Compilation error 0 ms 0 KB 2024-04-17 07:07:05 2024-04-17 07:07:06
→ Source
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::lower_bound;
using std::map;
using std::min;
using std::multiset;
using std::ostream;
using std::pair;
using std::priority_queue;
using std::queue;
using std::set;
using std::string;
using std::unordered_map;
using std::unordered_set;
using std::vector;
using pii = pair<int, int>;

template <typename T_container, typename T = typename std::enable_if<
                                    !std::is_same<T_container, string>::value,
                                    typename T_container::value_type>::type>
ostream &operator<<(ostream &os, const T_container &v);

template <typename A, typename B>
ostream &operator<<(std::ostream &os, const pair<A, B> &p) {
  return os << '(' << p.first << ", " << p.second << ')';
}
template <typename T_container, typename T>
ostream &operator<<(ostream &os, const T_container &v) {
  os << '{';
  string sep;
  for (const T &x : v) os << sep << x, sep = ", ";
  return os << '}';
}
void dbg_out() { cerr << endl; }
template <typename Head, typename... Tail>
void dbg_out(Head H, Tail... T) {
  cerr << ' ' << H;
  dbg_out(T...);
}
#define LOCAL
#ifdef LOCAL
#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif

struct Edge {
  int end;
  long long weight;
  bool isRoad;
};

class Comp {
 public:
  bool operator()(const Edge &e1, const Edge &e2) {
    return e1.weight > e2.weight;
  }
};

void dij(vector<vector<Edge>> &g, vector<long long> &shortestDist,
         vector<bool> &reachedMinViaRoad) {
  // yield the edge with the lowest weight
  priority_queue<Edge, vector<Edge>, Comp> pq;
  pq.push({1, 0, false});
  while (!pq.empty()) {
    Edge curEdge = pq.top();
    pq.pop();
    long long curWeight = curEdge.weight;
    int curNode = curEdge.end;
    if (shortestDist[curNode] != -1) {
      if (curWeight > shortestDist[curNode]) {
        continue;
      } else if (curWeight == shortestDist[curNode]) {
        reachedMinViaRoad[curNode] =
            reachedMinViaRoad[curNode] || curEdge.isRoad;
        continue;
      } else {
        __builtin_unreachable();
      }
    }
    shortestDist[curNode] = curEdge.weight;
    reachedMinViaRoad[curNode] = curEdge.isRoad;
    for (Edge outEdge : g[curEdge.end]) {
      outEdge.weight += curEdge.weight;
      pq.push(outEdge);
    }
  }
}

void dij(vector<vector<Edge>> &g, vector<long long> &shortestDist,
         vector<bool> &reachedMinViaRoad) {
  priority_queue<Edge, vector<Edge>, Comp> pq;
  pq.push({1, 0, false});
  while (!pq.empty()) {
    Edge curEdge = pq.top();
    pq.pop();
    // Dijkstra's algorithm guarantees that the first time we visit the node,
    it
        // will be the shortest path. Getting in this if statement would mean
        that
        // this is not the first time we are seeing this
        if (shortestDist[curEdge.end] != -1) {
      // if the current path is a longer path, discard
      if (curEdge.weight > shortestDist[curEdge.end]) {
        continue;
      }
      // if the current path has the same weight as a previously found path,
      // check if we can use a road to reach this node
      else if (curEdge.weight == shortestDist[curEdge.end]) {
        reachedMinViaRoad[curEdge.end] =
            reachedMinViaRoad[curEdge.end] || curEdge.isRoad;
        // We already processed this node before, so continue
        continue;
      }
      // Again: the algorithm guarantees that the first time we visit the
      node
          // will be the shortest path, so there is no way we can have a shorter
          // path if we have visited a node before
          else {
        __builtin_unreachable();
      }
    }
    shortestDist[curEdge.end] = curEdge.weight;
    reachedMinViaRoad[curEdge.end] = curEdge.isRoad;
    for (Edge outEdge : g[curEdge.end]) {
      outEdge.weight += curEdge.weight;
      pq.push(outEdge);
    }
  }
}

int main() {
  cin.tie(0);
  cout.tie(0);
  int numCities, numRoads, numTrainRoutes;
  cin >> numCities >> numRoads >> numTrainRoutes;
  vector<vector<Edge>> g(numCities + 1);
  for (int i = 0; i < numRoads; i++) {
    int start, end, weight;
    cin >> start >> end >> weight;
    g[start].push_back({end, weight, true});
    g[end].push_back({start, weight, true});
  }
  vector<Edge> allTrainRoutes;
  for (int i = 0; i < numTrainRoutes; i++) {
    int end, weight;
    cin >> end >> weight;
    g[1].push_back({end, weight, false});
    g[end].push_back({1, weight, false});

    allTrainRoutes.push_back({end, weight, false});
  }
  vector<long long> shortestDist(numCities + 1, -1);
  vector<bool> reachedMinViaRoad(numCities + 1, false);
  dij(g, shortestDist, reachedMinViaRoad);
  int ans = 0;
  vector<int> tot(numCities + 1, 0);
  for (size_t i = 0; i < numTrainRoutes; i++) {
    int end = allTrainRoutes[i].end;
    long long routeWeight = allTrainRoutes[i].weight;
    // if i was able to get to the city(
    //     from 1) with some weight less than the
    //     route's weight, I wanna remove this route
    if (routeWeight > shortestDist[end]) {
      ans++;
    } else if (shortestDist[end] == routeWeight) {
      if (reachedMinViaRoad[end]) {
        ans++;
      } else {
        tot[end]++;
      }
    } else {
      __builtin_unreachable();
    }
  }

  for (int i = 1; i < numCities + 1; i++) {
    if (tot[i]) {
      ans += tot[i] - 1;
    }
  }

  cout << ans << endl;
  return 0;
}
?
Time: ? ms, memory: ? KB
Verdict: ?
Input
?
Participant's output
?
Jury's answer
?
Checker comment
?
Diagnostics
?
Click to see test details