您的位置:首页 > 其它

POJ 1419--Graph Coloring(最大团求二着色问题)

2014-07-26 12:14 537 查看
题目要求:无向图G中二着色,也即是求一最大规模点集V‘是V子集,其中任意两点在图中没有边连接,也即是求最大独立集。最大独立集是G的补图的最大团(Max Clique),最大团和最大独立集相反,其中任意两点都有边连接。显然最大独立集中的点在G的补图中都应该连接,这些点集合成一个团。若它不是最大团,假设补图中有一个更大的团,则对其再求补图,可知团中的点在其补图中是不连接的,则是一个规模更大的独立集。
DFS求最大团:参考 http://www.cnblogs.com/zhj5chengfeng/archive/2013/07/29/3224092.html
算法基本思路:把最大团中的点按升序排列,设团集合为v0,v1,......,vk。显然这些点都在相互的邻接表当中,则我们先把v0的邻接点放入集合U0,然后再选出v1在U0中的邻接点放到U1,....,直到Uk的元素个数为0,则深搜回溯。因为不知道v0是图中那个点,所以我们需要遍历从所有点出发的最大团。
遍历的一些技巧:从最大点开始逆序遍历,设cliqueSize[i]为v[i]到v
中的点组成的最大团,显然cliqueSize
= 1,且cliqueSize[i+1] <= cliqueSize[i] <= cliqueSize[i+1]+1。
根据以上思路可以得出剪枝的一些技巧

如果在从vi开始搜索时,maxCliqueSize被更新(只会增加1),因为更新前maxCliqueSize = cliqueSize[i+1],所以再从v[i]出发的团规模不会再增加,可以直接返回从v[i-1]出发再搜索。
如果剩余点数加上当前团规模小于等于最大团规模,则返回0.
如果当前团规模加上将要深搜的点已求出的最大团规模小于等于最大团规模,返回0。

#include<cstdio>
#include<cstring>
#define maxN 102

int nodeNum;
int maxCliqueSize;
char g[maxN][maxN];
char blackNode[maxN],tmpBlackNode[maxN];
char cliqueSet[maxN][maxN],cliqueSize[maxN];

int DFS(int adjNum,int tmpCliqueSize)
{
if(adjNum == 0)
{
if(tmpCliqueSize > maxCliqueSize)             //当前团规模为已求得最大团规模加一
{
maxCliqueSize = tmpCliqueSize;
memcpy(blackNode,tmpBlackNode,sizeof(blackNode));
return 1;
}
return 0;
}
int i,j;
int newNode;
int nextAdjNum;
for(i = 0;i < adjNum;i++)
{
nextAdjNum = 0;
newNode = cliqueSet[tmpCliqueSize][i];
if(tmpCliqueSize+adjNum-i <= maxCliqueSize) return 0;            //当前团规模加上剩余点数小于等于已知最大团规模
if(tmpCliqueSize+cliqueSize[newNode] <= maxCliqueSize) return 0;    //当前团规模加上即将搜索的点的最大团规模小于等于已知所有点最大团规模
for(j = i+1;j < adjNum;j++)
{
if(g[newNode][cliqueSet[tmpCliqueSize][j]])
cliqueSet[tmpCliqueSize+1][nextAdjNum++] = cliqueSet[tmpCliqueSize][j];
}
tmpBlackNode[tmpCliqueSize+1] = newNode;
if(DFS(nextAdjNum,tmpCliqueSize+1))   return 1;
}
return 0;
}

int maxClique()
{
int i,j;
int adjNum;
maxCliqueSize = 0;
for(i = nodeNum;i >= 1;i--)
{
adjNum = 0;
for(j = i+1;j <= nodeNum;j++)
{
if(g[i][j])
cliqueSet[1][adjNum++] = j;
}
tmpBlackNode[1] = i;
DFS(adjNum,1);
cliqueSize[i] = maxCliqueSize;
}
return 0;
}

int generateGraph(char* str)
{
int a,b;
a = b = 0;
while(*str != ' ')
{
a *= 10;
a += *(str++)-'0';
}
while(*(++str))
{
b *= 10;
b += *str-'0';
}
g[a][b] = g[b][a] = 0;
return 0;
}

int main()
{
int i,T;
char tmp[10];
int edgeNum;
scanf("%d",&T);
while(T--)
{
memset(g,1,sizeof(g));
scanf("%d%d",&nodeNum,&edgeNum);
getchar();
while(edgeNum--)
{
gets(tmp);
generateGraph(tmp);
}
maxClique();
printf("%d\n",maxCliqueSize);
for(i = 1;i <= maxCliqueSize;i++)
{
printf("%d",blackNode[i]);
if(i != maxCliqueSize) printf(" ");
else printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: