Господа кодфорцесеры, вот задачка: Расследование
Решаю самым банальным алгоритмом так:
#include <fstream>
#define LL long long
#define MAXN 1e6 + 1
using namespace std;
fstream in("input.txt"),
out("output.txt", std::ios::out);
int G[101][101], N, t, i, k;
int Parent(int u)
{
if(u-- == 1)
return 1;
int _t = 0;
for(; !G[u][_t]; _t++);
return _t + 1;
}
int Depth(int u)
{
int k = 0;
while(u != 1)
u = Parent(u), k++;
return k;
}
int main()
{
for(in >> N >> _a >> _b; in >> t; i++)
G[t - 1][i + 1] = G[i + 1][t - 1] = 1;
int ha = Depth(_a), hb = Depth(_b);
while(ha != hb)
if(ha > hb)
_a = Parent(_a), ha--;
else
_b = Parent(_b), hb--;
while(_a != _b)
_a = Parent(_a), _b = Parent(_b);
out << _a;
return 0;
}
Сложность O(h)
но получаю TL в 11 тесте, хотя максимальное значение h 29999
вроде не должно TL давать. Подскажите пожалуйста в чем проблема?
int G[101][101]
— при N<=30000 это не самая удачная идея. Нужно хранить граф иначе — списками смежности, или банально предками, как во входных данных.А так у нас, во-первых, выход за пределы массива (и ML при нормальном размере массива), во вторых — сложность N^2 вместо N.
Спасибо всем большое))
Хотел бы узнать а почему сложность O(N*N) ?
Разве не O(H) ? H — максимальная высота дерева.
Ниже proVIDec уже написал. Пускай у нас есть граф вида 1->2->3->4->...->n. Тогда при вызове Depth(N) сначала будет n-1 операция в Parent(n), из-за цикла for(; !G[u][_t]; _t++);, потом еще n-2 операции в Parent(n-1), и так далее вверх по цепочке.
Нету смысла усложнять себе жизнь, и если значение parent[x] дано во входных данных — можно его сохранить в массив, и возвращать за О(1), а не перебирать.
1)
int G[101][101]
Эмм... N ≤ 300002)
int Parent(int u)
работает за O(N)3)
int Depth(int u)
вызываетint Parent(int u)
O(N) раз.4) Итого
int Depth(int u)
работает за O(N2)Вывод: хранить граф списком смежности, то есть
vector<int> G[MAXN]
.спасибо, никогда не сталкивался с этим, не хранил граф никак, кроме матрицы смежности, хотел бы узнать, а как они(смежные вершины) будут храниться в списке? придется ли алгоритмы переписывать?
Я сделал таким образом:
Но уверен, что не правильно, это та же матрица смежности :D
В
G[v]
хранятся все смежные с v вершины.Если придерживаться Вашего стиля:
Хотя мне кажется, что где-то тут ± 1-error :)
Если не заморачиваться, то vector хранит только добавленные элементы (на самом деле это почти так), то есть список смежности будет занимать O(M) памяти, где M — количество ребер.
Теперь для данной вершины вместо перебора всего ряда в матрице смежности, нужно перебирать вершины из списка этой вершины.
Можно решить не используя вектор.
Решение: Давайте сделаем массив p[], где p[x] — предок вершины x. И наибольший общий предок можно найти втупую, находишь всех предков X за O(h), помечаешь их в массиве used, а потом среди предков Y находишь отмеченную в used. В общем, примерно так: