@VerNika

Поиск хроматического индекса графа. Точный алгоритм методом перебора возможных окрасок рёбер. Как оптимизировать?

Необходимо реализовать точный алгоритм поиска хроматического индекса графа (минимального числа красок, которыми можно окрасить рёбра графа, чтобы никакие смежные ребра не были окрашены в один и тот же цвет).

Пусть ρ - максимальная степень вершины в графе. Тогда граф можно окрасить иногда ρ или всегда ρ + 1 цветами. Неточный алгоритм всегда справляется с раскраской в ρ + 1 цветов и не всегда в ρ цветов, он реализован. Теперь необходимо реализовать точный алгоритм для поиска раскраски в ρ цветов, если такая возможна. Как мне подсказали здесь такой алгоритм реализуется только полным перебором. Сделала, для графа, который в том же вопросе, он выполняется около минуты.

Код:
QList< QList<Edge> > colorEdges; //Окрашенные рёбра, colorEdges[i] - цвет, colorEdges[i][j] - ребро
QList<Edge> bufferVertex; //Список рёбер
/**/
maxDegree = 4; //Потом максимальной степени вершины
bool f;
int *colors = new int[bufferVertex.size()]; //Массив для хранения возможных комбинаций цветов
for (int i = 0; i < bufferVertex.size(); i++)
    colors[i] = 0;
do
{
    f = false;
    for (int i = 0; i < bufferVertex.size(); i++) //Перебор возможный комбинаций цветов
        if ((colors[i] + 1) != maxDegree)
        {
            colors[i]++;
            for (int j = i - 1; j > -1; j--)
                colors[j] = 0;
            break;
        }

    colorEdges.clear();
    for (int i = 0; i < maxDegree; i++) //Окраска в текущую комбинация цветов
        colorEdges.append(QList<Edge>());
    for (int i = 0; i < bufferVertex.size(); i++)
        colorEdges[colors[i]].append(bufferVertex.at(i));
        for (int j = 0; j < colorEdges[i].size(); j++)
            for (int k = j + 1; k < colorEdges[i].size(); k++)
                if ((colorEdges[i][j].getStart() == colorEdges[i][k].getStart()) ||
                   (colorEdges[i][j].getStart() == colorEdges[i][k].getEnd()) ||
                   (colorEdges[i][j].getEnd() == colorEdges[i][k].getStart()) ||
                   (colorEdges[i][j].getEnd() == colorEdges[i][k].getEnd()))
                    f = true;

    if (f) //Если окрасился неправильно, проверяем не закончился ли счётчик
    {
        f = false;
        for (int i = 0; i < bufferVertex.size(); i++)
            if (colors[i] != (maxDegree - 1))
            {
                f = true;
                break;
            }
    }
} while (f);


Как можно его хоть более-менее оптимизировать?
  • Вопрос задан
  • 1700 просмотров
Решения вопроса 1
AtomKrieg
@AtomKrieg
Давай я поищу в Google за тебя
Конечно, доступ к элементу list линейно зависит от размера контейнера. И дополнительные проверки на f==true в тела циклов вставил.
Ну и по коду комментарии немного

//Список рёбер
// QList<Edge> bufferVertex; 
std::vector<Edge> bufferVertex;

//Потом максимальной степени вершины
maxDegree = 4; 
//нужно 2 булевы переменные
bool f;

//Окрашенные рёбра, colorEdges[i] - цвет, colorEdges[i][j] - ребро
// QList< QList<Edge> > colorEdges;
std::vector<std::vector<Edge>> colorEdges(maxDegree);
for (int i = 0; i < colorEdges.size(); i++){
	colorEdges[i].reserve(bufferVertex.size());
}

//Потом максимальной степени вершины
// int *colors = new int[bufferVertex.size()];
// for (int i = 0; i < bufferVertex.size(); i++)
//     colors[i] = 0;

std::vector<int> colors(bufferVertex.size(), 0);

do
{
	f = false;
	//Перебор возможный комбинаций цветов
	for (int i = 0; i < colors.size(); i++) 
		if (colors[i] != maxDegree-1)
		{
			colors[i]++;
			for (int j = i - 1; j > -1; j--)
				colors[j] = 0;
			break;
		}

	//Окраска в текущую комбинация цветов
	// colorEdges.clear();

	//удалять объекты внутри не надо, а просто их чистим 
	for (int i = 0; i < colorEdges; i++){
		colorEdges[i].clear();
	} 
	
	for (int i = 0; i < bufferVertex.size(); i++){

		colorEdges[colors[i]].push_back(bufferVertex[i]);
		
		//нужен ли этот 2ой цикл снизу, может достаточно проверять только последнее вставленное значени?
		//for (int j = 0; j < colorEdges[i].size()-1 && !f; j++){
		// 		auto start_j = colorEdges[i][j].getStart();
		// 		auto end_j = colorEdges[i][j].getEnd();
		// 		auto start_k = colorEdges[i].back().getStart();
		// 		auto end_k = colorEdges[i].back().getEnd();
		// 		f = start_j==start_k || start_j == end_k || end_j == start_k || end_j==end_k;
		// }		
			for (int j = 0; j < colorEdges[i].size() && !f; j++)
				for (int k = j + 1; k < colorEdges[i].size() && !f; k++)
				{
					// if ((colorEdges[i][j].getStart() == colorEdges[i][k].getStart()) ||
					//    (colorEdges[i][j].getStart() == colorEdges[i][k].getEnd()) ||
					//    (colorEdges[i][j].getEnd() == colorEdges[i][k].getStart()) ||
					//    (colorEdges[i][j].getEnd() == colorEdges[i][k].getEnd()))
					// 	f = true;
					auto start_j = colorEdges[i][j].getStart();
					auto end_j = colorEdges[i][j].getEnd();
					auto start_k = colorEdges[i][k].getStart();
					auto end_k = colorEdges[i][k].getEnd();
					f = start_j==start_k || start_j == end_k || end_j == start_k || end_j==end_k;
				}
	}

	if (f) //Если окрасился неправильно, проверяем не закончился ли счётчик
	{
		f = false;
		for (int i = 0; i < bufferVertex.size() && !f; i++)
			f =  colors[i] != (maxDegree - 1);
	}
} while (f);
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы