众所周知,图的着色顶点是NP完全的。 众所周知,有效的贪婪算法可以得到近似的解决方案。 为什么不使用这些随机贪婪算法来计算k颜色的颜色,然后使用一些较慢的算法来减少k?
在我的情况下,我知道足够颜色图G的最小颜色数量 - 我们称之为K.我还设法实现了SL算法,它给了我(K + 2)颜色。一种颜色仅用于为一个顶点着色,因此我设法通过手动重新着色其他一些节点来删除它。因此,我有(K + 1)颜色,并且想编写一个能够将K(或更确切地说是K + 1)减少1的算法。
我试图手动完成 - 我发现一种颜色用于由相同颜色着色的最小数量的顶点,并将此颜色的使用减少到3.我必须重新着色3个节点。
一个想法是进行3次递归调用 - 每个颜色很深的节点一次。让我们分析递归函数对节点v必须做什么。它必须检查除了v的颜色和我们想要删除的颜色之外的每种颜色。因此,对于每种颜色c,它应该将v的颜色设置为c,并对每个节点进行递归调用,该节点是v的邻居并且具有颜色c。检查完所有颜色后,我们应检索v的旧颜色并重新设置。还有一个优化可能不是试图将v的颜色更改为超过其邻居x的颜色(因为递归树太深) - 但是对于太小的x,它可能根本无法改变颜色。 / p>
另一个想法是检查颜色可以改变的节点(不是我们想要删除的颜色),这样就不会碰到邻居的颜色。并进行递归调用以更改其他节点的颜色,直到我们要删除的一种颜色将重新着色。
这是我对第一个算法的实现,该算法旨在用于n< 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;
}
任何想法如何让它更快?
答案 0 :(得分:2)
我只是简单地查看了代码,并阅读了你的解释,但似乎你进入了一个无限循环,在邻居之间来回切换。你需要在每个节点中存储一个标志,以指出它当前正在重新着色,并且只能递归到那些当前没有被重新加工的邻居。
然而 - 这个算法在最坏的情况下看起来像是指数 - 而且我很确定有些情况下,K色图不能在不改变大部分图形的情况下重新成为K-1图形,甚至如果颜色K的节点数仅为1。
这是一个简单拓扑图。很明显它可以是两种颜色(R,G),我们有三种颜色版本使用(R,G,B)。正确重新着色的唯一方法是更改大约1/2节点颜色,最后是下面的其他版本之一。 ()
表示颜色B的单个节点,[]
表示需要重新着色的部分。
3 colour version : R-G-R-G-R-G-(B)-R-G-R-G-R-G-R
2 colour version 1: [R-G-R-G-R-G- R]-G-R-G-R-G-R-G
2 colour version 2: G-R-G-R-G-R-[G -R-G-R-G-R-G-R]
这意味着您(潜在指数)搜索的最小深度可能超过节点数量的1/2。这个可能会杀死合理的性能时间(或者可能不会取决于我猜测的图形的拓扑结构。)