Блог пользователя polosatic

Автор polosatic, история, 4 часа назад, По-русски

Недавно я решал эту задачу. Очевидно, тут нужны компоненты сильной связности. Я их написал и получил TL14: 277474774.

Я знал, что пушбэки в 1e6 веторов очень медленные из-за динамической реаллокации. Я также знал единственный способ исправить это: предподсчитать размер каждого вектора, и интерепретировать vector<vector> как один статический массив. Реализовывать это было неприятно, но я справился и получил TL38: 277476691

Я пытался добавить разные оптимизации: убирал последний вектор Эйлерова обхода, добавлял прагмы, но решение не проходило 38 тест. Поэтому, у меня возникло 2 вопроса для самых опытных оптимизаторов:

  1. Есть ли другой, более простой способ ускорить пушбэки в векторы, без предподсчета размера каждого вектора?

  2. Почему мое решение падает по TL и как его ускорить? Ограничения до $$$10^6$$$ должны влезать в 2.5 секунды.

  • Проголосовать: нравится
  • +6
  • Проголосовать: не нравится

»
4 часа назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

sooo?

»
4 часа назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

If you know beforehand approximately how much space you need, you can probably call std::vector::reserve

  • »
    »
    4 часа назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Much time ago I have the same issue and tried vector.reserve(), but it also gave me TL. But that time precomputing of all sizes helped my solution to pass.

    • »
      »
      »
      4 часа назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Well, vectors in general is slower than static array, I'm not very sure about the specifics of it but seems like it's memory allocation mechanics are more complicated

»
4 часа назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Probably not the most useful idea, however does emplace_back work?

  • »
    »
    4 часа назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    I tried it when I met this issue in the first time. It also did not work, same as vector.reserve().

»
3 часа назад, # |
  Проголосовать: нравится +15 Проголосовать: не нравится

Mushrooms function works in sqrt(x)/2

For the vectors, the fastest way is to use something similar to bucket sort, which is to merge all vectors into one array.

»
3 часа назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится

My vector filled copy paste code for SCCs ACd in around half of the TL, so that probably isn't the cause unless there's some compiler specific wizardry going on. I'm pretty sure the comment above hit the spot: the mushrooms function is the cause.

»
только что, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Try to use a different way to store the graph.

Example of directed graph:

// n is vertex count
// m is edge count
int U[100005],V[100005],head[100005],to[100005];
void graph_init(){
	for(int i=1;i<=m;++i) scanf("%d",&U[i]),scanf("%d",&V[i]);
	for(int i=1;i<=m;++i) ++head[U[i]];
	for(int i=head[0]=1;i<=n;++i) head[i]+=head[i-1];
	for(int i=1;i<=m;++i) to[--head[U[i]]]=V[i];
	head[n+1]=m+1;
}

iterate over all edges from vertex v:

for(int e=head[v];e<head[v+1];++e){
	int u=to[e];
	// e is edge id
	// an edge from v to u
	// ...
}
But I don't want to change my code a lot.