您的位置:首页 > 其它

poj 1419

2016-04-10 18:45 155 查看
题目大意:

给一个无向图,要求给每个点染色,每两个黑色点之间不能有边,白色点可以。求最大黑色点数及染色方案。

这道题就是求此图的最大独立集,也就是求其补图的最大团。

**何为最大独立集呢(⊙o⊙)?

从图中选取n个点,这n个点之间任意两点之间没有边相连,就是此图的一个独立集。

**那么最大团呢(⊙o⊙)?

从图中选取n个点,这n个点之间任意两点之间有边相连,就是此图的一个团。

那么显然图的最大独立集就是其补图的最大团

如何求最大团

born-kerbosch算法告诉你

首先,朴素的STMD算法出场^_^

//伪代码
dfs(y--已取的点的集合,l待处理的点的集合,n--不取的点的集合){
//nn--n集合的size,其他同nn
if(nn==0&&ln==0)
y已经是最大团,return;
for(l中的每个点v){
dfs(y∪{v},l∩N(v),n∩N(v));
//N(v)为顶点v相邻的点。
l=l除去v;
n=n加入v;
}
}


详细代码>o<

void dfs(int d, int ny, int nl, int nn)
//d为搜索深度
{
if(nl == 0 && nn == 0) //nl==0搜索到终点,只有nn==0时,才是一个最大团
for(int i = 1; i <=nl; i ++)
{
int v = l[d][i];
int tnl= 0, tnn = 0;
for(int j = 1; j < =an; j ++) y[d + 1][j] = y[d][j];
y[d + 1][ny] = v;
for(int j = 1; j < =nl; j ++)if(g[v][l[d][j]]) l[d + 1][tnl ++] = l[d][j];
for(int j = 1; j < =nn; j ++) if(g[v][n[d][j]]) n[d + 1][tnn ++] = n[d][j];
dfs(d + 1, ny + 1, tnl, tnn);
//把v从y取出,放入n
l[d][i] = 0, n[d][nn ++] = v;
}
}


但是>o<这种算法太朴素了,我们还是剪一剪枝为好

对于任意的最大团,其必须包括顶点v或者v的非邻接点.否则就可以添加顶点v来扩充极大团.所以.我们只要测试 顶点v以及 v的非邻接点即可.这样可以节省递归的时间.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: