Блог пользователя ruslan.rakhimov

Автор ruslan.rakhimov, 10 лет назад, По-русски

При изучении алгоритма на e-maxx Проверка графа на ацикличность и нахождение цикла понял, что алгоритм прекращает работу при нахождении первого цикла. Как найти все циклы в графе? Я переделал исходный алгоритм. При реализации моего алгоритма, некоторые циклы упускаются из вида. Например:

Ребра в неориент. графе: 1 2 1 3 2 3 2 4 3 4 Циклы: 1 2 3 1 2 3 4 2 1 2 4 3 1

Мой алгоритм find_cycles() не находит третий цикл. Как можно это исправить?

int ncycle = 0;
vector<int> cycle[MAXN];
vector<int> g[MAXN];

int add_cycle(int cycle_end, int cycle_st)
{
	cycle[ncycle].clear();
	cycle[ncycle].push_back(cycle_st);
	for(int v = cycle_end; v != cycle_st; v = p[v])
		cycle[ncycle].push_back(v);
	cycle[ncycle].push_back(cycle_st);
	
	reverse(cycle[ncycle].begin(), cycle[ncycle].end());
	
	return cycle[ncycle].size();		
}
void dfs(int v)
{
	color[v] = 1;
	for(int i = 0; i < g[v].size(); i++)
	{
		int to = g[v][i];
		if(color[to] == 0)
		{
			p[to] = v;
			dfs(to);
		}
		else if(color[to] == 1)
		{
			CycleFound = true;
			if(add_cycle(v, to) > 3) // Исключение вырожденных случаев, н: 1 2 1
				ncycle++;
		}
	}
	color[v] = 0; // Исправлено. Было: color[v] = 2;
}
void find_cycles()
{
	for(int i = 0; i < n; i++)
		if(color[i] == 0)
			dfs(i);
}

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

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

Все циклы — это все простые циклы? (Если нет, то их обычно бесконечно много.)

В полном графе из n вершин различных простых циклов — порядка n!. Так что в любом случае решение, работающее для произвольного графа, будет не быстрее перебора. Перебор отличается от поиска в глубину тем, что при выходе из рекурсивной функции следует вообще снимать пометку (color[v] = 0;).

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

    При выходе она у меня снимается же? (color[v] = 2;)

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

      Вообще снимать — это вернуть в исходное состояние. Чтобы if(color[to] == 0) не отличил.

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

Циклов в графе может быть порядка O(NN). Вы все еще хотите их искать? :)

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

    Значит для задач это бысмысленное дело? Т.е. в задачах это не нужно?

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

Интересно, что можно "быстро" найти базис "простых циклов".

Или формально: сопоставим циклу битовую строку длинной E (число ребер), ясно, что сумма таких битовых строк даст битовую строку, соответствующую циркуляции. То есть можно найти базис в лин. пространстве циркуляций. Таким базисом будет следующий набор циклов: строим остовный лес, далее берем любое ребро не из леса, и получаем, отбросив ненужную часть леса, цикл. Несложно заметить, что это базис. таким образом размеренность пространства: E-(V-C), C-число компонент связности.

  • »
    »
    10 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится -13 Проголосовать: не нравится

    Лучше бы дали ссылку, например, сюда или на какую-нибудь книгу. Потому что если человек не сильно хорошо разбирается в линейной алгебре (а таких тут, кажется, большинство), то ему с Вашего объяснения ничего ясно не будет.