Official

C - Who is Saikyo? Editorial by en_translator


The key to this problem is to figure out the conditions that there is exactly one candidate of the strongest programmer. If you choose a bad approach here, the implementation will be harder.
Taking a close look at the conditions, the problem turns out to be able to be solved by the following algorithm.

  • Let \(s[i]\) be an array to count how many people are stronger than person \(i\). The array is initialized with \(0\).
  • For \(i=1,2,\dots,M\) in order, add \(1\) to \(s[A[i]]\).
  • If exactly one \(x\) satisfies \(s[x] = 0\), that \(x\) is the answer; if two or more do, the answer is -1.

The validity of the algorithm is too complicated to entirely explain, so we will describe some key observations.

Consider the situation illustrated below. (\(1 \gets 2\) means “person \(1\) is stronger than person \(2\)”; same applies to the other arrows)

image1

Then, there are two ways to decide superiorities to satisfy the transitivity, as in the problem statement:

image2

See the relations on the left; notice that there is an ordering like “\(1\) is the strongest, followed by \(2\), then \(3\), and \(4\) is the worst.” In other words, in the sequence \(1, 2, 3, 4\), “a person on the left is stronger than one on the right.”

The relations on the right also has a sequence \(1, 2, 4, 3\) that satisfies the same condition: “a person on the left is stronger than one on the right.”

As you can see, when we assign the superiorities so that the conditions in the problem statement are satisfied, there exists a permutation \(p\) of \(1, 2, \dots, N\) that is sorted by their strength. (Such a relation is called a total ordering.)

By this fact, for two propositions \(P\) and \(Q\) defined by

  • \(P\): there are exactly one person with \(s[x] = 0\); and
  • \(Q\): the strongest programmer is determined to be person \(x\),

two lemmas that “if \(P\), then \(Q\)” and “if not \(Q\), then not \(P\)” can be proved; thus, the validity of the algorithm is asserted.
The complexity is \(\mathrm{O}(N + M)\), which is fast enough.

  • Sample code (C++)
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N, M;
  cin >> N >> M;
  vector<int> deg(N);

  for (int _ = 0; _ < M; _++) {
    int a, b;
    cin >> a >> b;
    --a, --b;
    deg[b]++;
  }
  int ans = -1;
  for (int i = 0; i < N; i++) {
    if (deg[i] == 0) {
      if (ans != -1) {
        cout << -1 << endl;
        exit(0);
      } else {
        ans = i + 1;
      }
    }
  }
  cout << ans << endl;
}

posted:
last update: