Общеизвестно, что окрашивающие вершины графа NP-полны. Известно также, что существуют эффективные жадные алгоритмы, которые могут получить приблизительное решение. Почему бы не использовать эти рандомизированные жадные алгоритмы для расчета цвета с k цветами, а затем использовать некоторые более медленные алгоритмы для уменьшения k?Дано k-раскраска вершин графа (k-1) -краска
В моей ситуации я знаю минимальное количество цветов, достаточных для цветного графа G - назовем его K. Мне также удалось реализовать алгоритм SL, который дал мне (K + 2) -цвет. Один цвет использовался только для окраски одной вершины, поэтому мне удалось удалить ее, вручную перекрасив некоторые другие узлы. Поэтому у меня есть (K + 1) -коррекция и хотелось бы написать алгоритм, который бы уменьшил K (или, скорее, K + 1) на 1.
Я попытался сделать это вручную - я нашел цвет, который используется в минимальном количестве вершин, окрашенных одним и тем же цветом, и уменьшает использование этого цвета до 3. Я должен перекрасить только 3 узла.
Одна из идей - сделать 3 рекурсивных вызова - по одному для каждого плохого цвета. Давайте проанализируем, что рекурсивная функция должна была бы выполнить для узла v. Он должен был бы проверять каждый цвет отдельно от цвета v и того, который мы хотели бы удалить. Поэтому для каждого цвета c он должен установить цвет v в c и сделать рекурсивный вызов для каждого узла, который является соседом v и имеет цвет c. После проверки всех цветов мы должны получить старый цвет v и снова установить его. Еще одна оптимизация может не пытаться изменить цвет v на тот, который больше, чем у его соседей (поскольку дерево рекурсии будет слишком глубоким), но для слишком маленького x он вообще не сможет изменить цвет.
Другая идея - проверить узлы, цвет которых можно изменить (а не цвет, который мы хотим удалить), чтобы он не сталкивался с цветами соседей. И сделайте рекурсивные вызовы для изменения цветов других узлов, пока один цвет, который мы хотим удалить, будет перекрашен.
Вот моя реализация первого алгоритма, который был предназначен для работы на п < 90, но, кажется, не до конца (500 минут исполнения):
#include<stdio.h>
#include<assert.h>
#include<vector>
using namespace std;
vector<int> graph[99];
int hash[10009], color[99];
const int colors = 9, color_to_change = 7;
void change_color(int v)
{
int tmp = color[v], count;
for(int i = 1; i <= colors; ++i)
{
count = 0;
for(int j = 0; j < graph[v].size(); ++j)
count += color[graph[v][j]] == i;
if(!count)
{
color[v] = i;
return;
}
if(count < 4 && i != color_to_change && i != color[v])
{
color[v] = i;
for(int j = 0; j < graph[v].size(); ++j)
if(color[graph[v][j]] == i)
change_color(graph[v][j]);
}
}
color[v] = tmp;
}
int main()
{
int n, m, a, b, max = 0, j = -1;
scanf("%d%d", &n, &m);
while(m--)
{
scanf("%d%d", &a, &b);
assert(a != b);
if(hash[a*100+b] || hash[b*100+a])
continue;
assert(a*100+b < 10000 && b*100+a < 10000);
hash[a*100+b] = hash[b*100+a] = 1;
graph[a].push_back(b);
graph[b].push_back(a);
}
for(int i = 1; i <= n; ++i)
scanf("%d", &color[i]);
for(int i = 1; i <= n; ++i)
if(color[i] == color_to_change)
change_color(i);
for(int i = 1; i <= n; ++i)
printf("%d ", color[i]);
return 0;
}
Любые идеи, как сделать это быстрее?
Это еще NP-жесткий. Можете ли вы указать, какое решение вы ищете? – templatetypedef
Это NPH, но для небольших графиков, таких как my (n <90), некоторые условия, которые уменьшат дерево рекурсии и небольшое количество узлов, которые необходимо изменить, возможно, можно добиться раскраски (и я знаю, что это так). – user1
Рассматривали ли вы использование общего решения SAT или ILP? –