Problem: ioi18_e
Categories: graph, search
Difficulty: hard
Time limit: 1000 ms | Memory limit: 512 MB

In Japan, cities are connected by a network of highways. This network consists of $N$ cities and $M$ highways. Each highway connects a pair of distinct cities. No two highways connect the same pair of cities. Cities are numbered from $0$ through $N-1,$ and highways are numbered from $0$ through $M-1.$ You can drive on any highway in both directions. You can travel from any city to any other city by using the highways.

A toll is charged for driving on each highway. The toll for a highway depends on the traffic condition on the highway. The traffic is either light or heavy. When the traffic is light, the toll is $A$ yen (Japanese currency). When the traffic is heavy, the toll is $B$ yen. It's guaranteed that $A < B.$ Note that you know the values of $A$ and $B.$

You have a machine which, given the traffic conditions of all highways, computes the smallest total toll that one has to pay to travel between the pair of cities $S$ and $T (S \neq T),$ under the specified traffic conditions.

However, the machine is just a prototype. The values of $S$ and $T$ are fixed (i.e., hardcoded in the machine) and not known to you. You would like to determine $S$ and $T.$ In order to do so, you plan to specify several traffic conditions to the machine, and use the toll values that it outputs to deduce $S$ and $T.$ Since specifying the traffic conditions is costly, you don't want to use the machine many times.

Implementation details

You should implement the following procedure:

find\_pair(int N, int[] U, int[] V, int A, int B)

* $N$: the number of cities.
* $U$ and $V$: arrays of length $M,$ where $M$ is the number of highways connecting cities. For each $i : 0 \le i \le M-1,$ the highway $i$ connects the cities $U[i]$ and $V[i].$
* $A$: the toll for a highway when the traffic is light.
* $B$: the toll for a highway when the traffic is heavy.
* This procedure is called exactly once for each test case.
* Note that the value of $M$ is the lengths of the arrays, and can be obtained as indicated in the implementation notice.

int64 ask(int[] w)

* The length of $w$ must be $M.$ The array $w$ describes the traffic conditions.
* For each $i: 0 \le i \le M-1, w[i]$ gives the traffic condition on the highway $i.$ The value of $w[i]$ must be either $0$ or $1.$
  + $w[i] = 0$ means the traffic of the highway $i$ is light.
  + $w[i] = 1$ means the traffic of the highway $i$ is heavy.
* This function returns the smallest total toll for travelling between the cities $S$ and $T,$ under the traffic conditions specified by $w.$
* This function can be called at most $100$ times (for each test case).

find\_pair should call the following procedure to report the answer:

answer(int s, int t)

* s and t must be the pair $S$ and $T$ (the order does not matter).
* This procedure must be called exactly once.

If some of the above conditions are not satisfied, your program is judged as Wrong Answer. Otherwise, your program is judged as Accepted and your score is calculated by the number of calls to ask (see Subtasks).

Constraints

* $2 \le N \le 90\,000$
* $1 \le M \le 130\,000$
* $1 \le A < B \le 1\,000\,000\,000$
* For each $i: 0 \le i M-1$
  + $0 \le U[i] \le N-1$
  + $0 \le V[i] \le N-1$
  + $U[i] \neq V[i]$
* $(U[i], V[i]) \neq (U[j], V[j])$ and $(U[i], V[j]) \neq (V[j], U[j])$ for all $i,j: 0 \le i < j \le M-1$
* You can travel from any city to any other city by using the highways.
* $0 \le S \le N-1$
* $0 \le T \le N-1$
* $S \neq T$

In this problem, the grader is NOT adaptive. This means that $S$ and $T$ are fixed at the beginning of the running of the grader and they do not depend on the queries asked by your solution.

Sample grader

The sample grader reads the input in the following format:

|  |  |  |  |  |
| --- | --- | --- | --- | --- |
| line | $1$ | : | $N$ $M$ $A$ $B$ $S$ $T$ |  |
| line | $2+i$ | : | $U[i]$ $V[i]$ | $(0 \le i \le M-1)$ |

If your program is judged as Accepted, the sample grader prints Accepted: q, with $q$ the number of calls to ask.

If your program is judged as Wrong Answer, it prints Wrong Answer: MSG, where MSG is one of:

* answered not exactly once: The procedure answer was not called exactly once.
* w is invalid: The length of $w$ given to ask is not $M$ or $w[i]$ is neither $0$ nor $1$ for some $i: 0 \le i \le M-1.$
* more than 100 calls to ask: The function ask is called more than $100$ times.
* {s, t} is wrong: The procedure answer is called with an incorrect pair $s$ and $t.$

Scoring

Subtasks

|  |  |  |
| --- | --- | --- |
| Subtask | Points (max) | Additional constraints |
| $1$ | $5$ | $M=N-1,$ one of $S$ or $T$ is $0,$ $N \le 100$ |
| $2$ | $7$ | $M=N-1,$ one of $S$ or $T$ is $0$ |
| $3$ | $6$ | $M=N-1,$ $U[i] = i,$ $V[i] = i+1$ for all $i: 0\le i \le M-1$ |
| $4$ | $33$ | $M=N-1$ |
| $5$ | $18$ | $A=1,$ $B=2$ |
| $6$ | $31$ | No |

Assume your program is judged as Accepted, and makes $X$ calls to ask. Then your score for $P$ the test case, depending on its subtask number, is calculated as follows:

|  |  |  |  |
| --- | --- | --- | --- |
| Subtask 1 | $P=5$ |  |  |
| Subtask 2 | If $X \le 60,$ | $P=7.$ | Otherwise $P=0.$ |
| Subtask 3 | If $X \le 60,$ | $P=6.$ | Otherwise $P=0.$ |
| Subtask 4 | If $X \le 60,$ | $P=33.$ | Otherwise $P=0.$ |
| Subtask 5 | If $X \le 52,$ | $P=18.$ | Otherwise $P=0.$ |
| Subtask 6 | If $X \le 50,$ | $P=31.$ | If $51\le X\le 52, P=21.$ |
|  |  |  | Otherwise $P=0.$ |

Note that your score for each subtask is the minimum of the scores for the test cases in the subtask.

Note

Example

Let $N=4,$ $M=4,$ $U=[0,0,0,1],$ $V=[1,2,3,2],$ $A=1,$ $B=3,$ $S=1,$ and $T=3.$

The grader calls find\_pair(4, [0, 0, 0, 1], [1, 2, 3, 2], 1, 3).

![](https://ioi.contest.codeforces.com/espresso/451ff65ba01e76034a1e4c53b7ae83741e667ce9.png)

In the figure above, the edge with number i corresponds to the highway i. Some possible calls to ask and the corresponding return values are listed below:

|  |  |
| --- | --- |
| Call | Return |
| ask([0, 0, 0, 0]) | $2$ |
| ask([0, 1, 1, 0]) | $4$ |
| ask([1, 0, 1, 0]) | $5$ |
| ask([1, 1, 1, 1]) | $6$ |

For the function call ask([0, 0, 0, 0]), the traffic of each highway is light and the toll for each highway is $1.$ The cheapest route from $S=1$ to $T=3$ is $1 \rightarrow 0 \rightarrow 3.$ The total toll for this route is $2.$ Thus, this function returns $2.$

For a correct answer, the procedure find\_pair should call answer(1, 3) or answer(3, 1).

The file sample-01-in.txt in the zipped attachment package corresponds to this example. Other sample inputs are also available in the package.

Interactor / grader files:
grader.cpp: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <utility>
#include <vector>
#include "highway.h"

namespace {

constexpr int MAX_NUM_CALLS = 100;
constexpr long long INF = 1LL << 61;

int N, M, A, B, S, T;
std::vector<int> U, V;
std::vector<std::vector<std::pair<int, int>>> graph;

bool answered, wrong_pair;
int num_calls;

int read_int() {
  int x;
  if (scanf("%d", &x) != 1) {
    fprintf(stderr, "Error while reading input\n");
    exit(1);
  }
  return x;
}

void wrong_answer(const char *MSG) {
  printf("Wrong Answer: %s\n", MSG);
  exit(0);
}

}  // namespace

long long ask(const std::vector<int> &w) {
  if (++num_calls > MAX_NUM_CALLS) {
    wrong_answer("more than 100 calls to ask");
  }
  if (w.size() != (size_t)M) {
    wrong_answer("w is invalid");
  }
  for (size_t i = 0; i < w.size(); ++i) {
    if (!(w[i] == 0 || w[i] == 1)) {
      wrong_answer("w is invalid");
    }
  }

  std::vector<bool> visited(N, false);
  std::vector<long long> current_dist(N, INF);
  std::queue<int> qa, qb;
  qa.push(S);
  current_dist[S] = 0;
  while (!qa.empty() || !qb.empty()) {
    int v;
    if (qb.empty() ||
        (!qa.empty() && current_dist[qa.front()] <= current_dist[qb.front()])) {
      v = qa.front();
      qa.pop();
    } else {
      v = qb.front();
      qb.pop();
    }
    if (visited[v]) {
      continue;
    }
    visited[v] = true;
    long long d = current_dist[v];
    if (v == T) {
      return d;
    }
    for (auto e : graph[v]) {
      int vv = e.first;
      int ei = e.second;
      if (!visited[vv]) {
        if (w[ei] == 0) {
          if (current_dist[vv] > d + A) {
            current_dist[vv] = d + A;
            qa.push(vv);
          }
        } else {
          if (current_dist[vv] > d + B) {
            current_dist[vv] = d + B;
            qb.push(vv);
          }
        }
      }
    }
  }
  return -1;
}

void answer(int s, int t) {
  if (answered) {
    wrong_answer("answered not exactly once");
  }

  if (!((s == S && t == T) || (s == T && t == S))) {
    wrong_pair = true;
  }

  answered = true;
}

int main() {
  N = read_int();
  M = read_int();
  A = read_int();
  B = read_int();
  S = read_int();
  T = read_int();
  U.resize(M);
  V.resize(M);
  graph.assign(N, std::vector<std::pair<int, int>>());
  for (int i = 0; i < M; ++i) {
    U[i] = read_int();
    V[i] = read_int();
    graph[U[i]].push_back({V[i], i});
    graph[V[i]].push_back({U[i], i});
  }

  answered = false;
  wrong_pair = false;
  num_calls = 0;
  find_pair(N, U, V, A, B);
  if (!answered) {
    wrong_answer("answered not exactly once");
  }
  if (wrong_pair) {
    wrong_answer("{s, t} is wrong");
  }
  printf("Accepted: %d\n", num_calls);
  return 0;
}

highway.cpp: #include "highway.h"

void find_pair(int N, std::vector<int> U, std::vector<int> V, int A, int B) {
  int M = U.size();
  for (int j = 0; j < 50; ++j) {
    std::vector<int> w(M);
    for (int i = 0; i < M; ++i) {
      w[i] = 0;
    }
    long long toll = ask(w);
  }
  answer(0, N - 1);
}

highway.h: #include <vector>

void find_pair(int N, std::vector<int> U, std::vector<int> V, int A, int B);

long long ask(const std::vector<int> &w);
void answer(int s, int t);