1

Тема: Хранение графа.

У меня такая задача: нужно представить граф в виде списка смежных вершин. В виде матрицы смежности не получиться потому-что по памяти не пройдёт. В виде списка смежных вершин я представить в принципе могу, но допустим у меня V вершин и E рёбер, тогда я беру двухмерный массив V на E или V на V, но это меня не устраивает. Я что-то слышал, что можно с помощью функций alloc и realloc реализовать, но не знаю как((. Помогите с способом представления или напишите на С реализацию функций.

Misha Panyavin [PML]

2

Re: Хранение графа.

И ещё ограничения на V - количество вершин и E - количество рёбер (2 ? V ? 10000, 1 ? E ? 10^5).

Misha Panyavin [PML]

3 Отредактировано KADR (2010-05-02 12:47:23)

Re: Хранение графа.

Я обычно пользуюсь двумя способами представления графа, оба занимают O(V+E) памяти.

1. Просто создадим массив векторов размера V и в i-й вектор будем пихать вершины, смежные с i. Выглядит так:

vector<int> sm[10001]; 
...
sm[10].push_back(23);
...

Но этот способ не всегда хорош тем, что векторы долго инициализируются по сравнению со статическими массивами и еще операции с ними выполняются дольше. Я даже из-за времени инициализации в 2008 году на республиканской олимпиаде школьников потерял 100 баллов и взял 3 диплом smile

2. Будем хранить граф в виде списка ребер, но хитро устроенного. Для каждой вершины заведем массив head, где будем хранить номер первого ребра в списке. Так же заведем массив ver, где в i-й ячейке будем хранить конец i-го ребра, а еще заведем массив nx, где для каждой ячейки где есть ребро будем хранить номер следующего ребра в списке. Выглядеть добавление ребра(если граф неориентированный, то будем добавлять еще и обратное ребро) будет так:

memset(head,-1,sizeof(head));
inline void add_edge(int v,int w)
{
  ver[m]=w; nx[m]=head[v]; head[v]=m++;
  ver[m]=v; nx[m]=head[w]; head[w]=m++;
}

Это был пример для неориентированного графа и если, к примеру, надо для ребра i узнать обратное, то номер у него будет i^1.

Чтобы пройти по всем смежным вершинам с v нужно написать что-то вроде:

for (int w=head[v];w>=0;w=nx[w])
{
  cout<<ver[w]<<endl;
}

4

Re: Хранение графа.

спасибо огромное, очень помог, спасибо задача прошла)))

Misha Panyavin [PML]

5

Re: Хранение графа.

to KADR:
Прикольная модификация списка ребер.
Сразу возникает жадный вопрос. Где такое вычитал? Может там еще че интересное накопаю smile

6

Re: Хранение графа.

Acmefan пишет:

to KADR:
Прикольная модификация списка ребер.
Сразу возникает жадный вопрос. Где такое вычитал? Может там еще че интересное накопаю smile

Вычитал я это когда-то давно в коде ACRush на кодджеме.

7

Re: Хранение графа.

А что здесь особенного?Насколько я понял, это стандартный связный список. Сразу начал читать описание - так и подумал, потом увидел комменты о том, что вычитал где-то у АCRush'a, перечитал описание, вроде бы ничего необычного не заметил. Мб для сишников это не проблема, но мне на паскале без связного списка на графы разве что Флойда писать можно:)

8

Re: Хранение графа.

Да нет, я не говорил что это необычное. Просто я честно ответил, где вычитал этот метод smile До этого писал всегда с массивом векторов смежных вершин.

9

Re: Хранение графа.

coder.ua пишет:

А что здесь особенного?Насколько я понял, это стандартный связный список.

Ну да, стандартный.
Но вот реализация понравилась.

10

Re: Хранение графа.

Реализация тоже smile