Я нашел решение этой проблемы.
Я предполагаю, что массивы инициализируются со всеми 0 (в противном случае N должен быть заполнен 0), и что M является матрицей смежности для графа. Я позволил n быть числом узлов (n = | V |).
j,i = 1;
N = new int[n]
while (j <= n && i <= n) {
if (N[i] == 1) {
i++
} else if (N[j] == 1) {
j++;
} else if (M[i,j] == 1) {
N[i] = 1
i++
} else if (i == j) {
j++
} else {
N[j] = 1
j++
}
}
for (z = 1 to n) {
if (N[z] == 0) {
return z
}
}
return NULL
Почему это работает (не формальное доказательство):
Любой узел с любыми ребрами, идущими от него, не является универсальным приемником. Таким образом, если M [i, j] равно 1 для любого j, я не могу быть стоком.
Если M [i, j] равно 0 для любого i, то у i нет ребра для j, и j не может быть универсальным стоком.
1 в N [i] обозначает, что я знаю, что это не приемник, и любой узел, который я знаю, не является приемником, может быть пропущен как для i, так и для j. Я останавливаюсь, когда либо превышает n.
Таким образом, я продолжаю проверять любые узлы, которые, как я до сих пор не знаю, не является приемником, пока не останется 1 или 0 возможных приемников.
Таким образом, любой узел, который все еще равен 0 в конце цикла, должен быть приемником, и их будет только 1 или 0.
Почему это O (n):
Это всегда увеличивает или я или j. Останавливается, когда либо превышает n. Таким образом, наихудший случай для цикла - 2n. Работа в цикле постоянна. Последний цикл - наихудший случай n. Следовательно, алгоритм O (3n) = O (n).
Это решение основано на идее проблемы знаменитости, которая является способом рассмотрения той же проблемы.