Змагання корів#10151

Змагання корів (Розбір)

Оголосимо булеву матрицю . Для кожної пари корів і встановимо g[a][b] = true, якщо корова перемагає корову . Таким чином, проведемо орієнтоване ребро від до . Оскільки результати раундів несуперечливі, побудований граф є ациклічним.

Ранг корови з номером можна визначити, якщо для будь-якої іншої корови відомо, яка з них сильніша: або корова може перемогти корову (можливо, через кілька проміжних корів), або корова може перемогти корову . Іншими словами, у транзитивному замиканні графа для кожної пари і повинна виконуватися хоча б одна з умов: g[i][j] = true або g[j][i] = true.

Одночасно обидва значення g[i][j] і g[j][i] не можуть дорівнювати , оскільки це означало б наявність протиріччя в результатах змагань.

Приклад

У наведеному прикладі можна однозначно визначити ранги лише для корів і .

Корова перемагає корову , але програє всім іншим коровам. Корова програє всім іншим коровам.

Для корови невідомо, чи зможе вона перемогти корів і . Аналогічно, для корів і невідомо, чи зможуть вони перемогти корову . Тому точні ранги цих корів визначити неможливо.

Реалізація алгоритму

Оголосимо булеву матрицю .

bool g[101][101];

Зчитуємо вхідні дані.

scanf("%d %d", 

Вважаємо, що кожна корова перемагає саму себе.

for (i = 1; i <= n; i++) g[i][i] = 1;

Зчитуємо вхідні дані. Будуємо вхідний граф. Якщо корова перемогла корову , проводимо ребро від до .

for (i = 0; i < m; i++)
{
  scanf("%d %d", 
  g[a][b] = 1;
}

Обчислюємо транзитивне замикання графа. Якщо з вершини у вершину існує шлях по ребрах графа, встановлюємо g[i][j] = true.

for (k = 1; k <= n; k++)
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
  if (g[i][k] 

У змінній накопичуємо кількість корів, для яких можна однозначно визначити ранг.

res = 0;

У циклі по черзі перевіряємо кожну корову і з'ясовуємо, чи можна однозначно визначити її ранг.

for (i = 1; i <= n; i++)
{

Перевіримо, чи можна визначити ранг корови з номером . Для цього переберемо всіх корів . Якщо для якоїсь корови виконуються обидві умови: g[i][j] = false і g[j][i] = false, то неможливо визначити, яка з двох корів сильніша. Отже, точний ранг корови з номером визначити не можна.

  bool good = true;
  for (j = 1; j <= n; j++)
    if (g[i][j] == false 
    {
      good = false;
     break;
    }

Якщо після перевірки всіх корів значення залишилося рівним , значить, для корови її положення відносно кожної іншої корови відоме. Отже, її ранг можна однозначно визначити.

  if (good) res++;
}

Виводимо відповідь.

printf("%d\n", res);