算法思路:
- 構建解空間樹(二叉樹)
- 以廣度優先遍歷解空間樹,對每個結點進行約束函數和限界函數判斷
- 約束函數:若要入選隊伍,則必須與其他隊員無仇
for(int j=i-1;j>0;bnode=bnode.parent,j--){
if(bnode.leftChild&&a[i][j]==1){
ok=false;
break;
}
- 約束函數:當前團最大結點大于最有解
if(cn+n-i>=bestn){//右子樹可能含有最優解
addLiveNode(cn+n-i,cn,i+1,enode,false);
}
- 當遍歷到其中一個葉子結點,則算法結束。
完整代碼如下:
import java.util.Collections;
import java.util.LinkedList;
class BBnode{ //構建結點類
BBnode parent;
boolean leftChild;
public BBnode(BBnode parent, boolean leftChild)
{
super();
this.parent = parent;
this.leftChild = leftChild;
}
}
class HeapNode implements Comparable{ //構建隊列結點
BBnode liveNode;
int upperSize; //當前團最大結點數(已知+未知)
int cliqueSize; //當前團頂點數
int level; //所處層數
public HeapNode(BBnode liveNode, int upperSize, int cliqueSize, int level)
{
super();
this.liveNode = liveNode;
this.upperSize = upperSize;
this.cliqueSize = cliqueSize;
this.level = level;
}
@Override
public int compareTo(Object o)
{
// TODO Auto-generated method stub
int xup=((HeapNode)o).upperSize;
if(upperSize<xup)return 1;
if(upperSize==xup)return 0;
return -1;
}
}
class MaxHeap{
int[] value;
int heapsize;
public void put(HeapNode node){
}
}
public class BBClique
{
static int[] x;
static int n;
static int cn;//當前隊伍人數
static int bestn;//最大隊伍人數
static int[] bestx;
static int[][] a;
static LinkedList<HeapNode> heap;
public BBClique(int[][] a){
this.a=a;
heap=new LinkedList<HeapNode>();
}
public void addLiveNode(int up,int size,int lev,BBnode par,boolean ch){
BBnode enode=new BBnode(par,ch);
HeapNode h=new HeapNode(enode,up,size,lev);
heap.add(h);
Collections.sort(heap);
}
public int bbMaxClique(int[] bestx){
int n=bestx.length-1;
heap= new LinkedList<HeapNode>();
//初始化(初始數據)
BBnode enode=null;
int i=1;
int cn=0;
int bestn=0;
//搜索子集空間樹
while(i!=n+1){//非葉節點
boolean ok=true;
BBnode bnode=enode;
for(int j=i-1;j>0;bnode=bnode.parent,j--){
if(bnode.leftChild&&a[i][j]==1){
ok=false;
break;
}
}
if(ok){//左兒子結點為可行結點
if(cn+1>bestn)
bestn=cn+1;
addLiveNode(cn+n-i+1,cn+1,i+1,enode,true);
}
if(cn+n-i>=bestn){//右子樹可能含有最優解
addLiveNode(cn+n-i,cn,i+1,enode,false);
}
//取下一個擴展結點
HeapNode node=heap.poll();
enode=node.liveNode;
cn=node.cliqueSize;
i=node.level;
}
//構造當前最優解
for(int j=n;j>0;j--){
bestx[j]=enode.leftChild?1:0;
enode=enode.parent;
}
return bestn;
}
public static void main(String[] args)
{
int[] c1={10,1,2,2,2,3,3,4,5,6,6,7,8,9};
int[] c2={12,2,4,3,6,5,6,5,6,8,10,9,10,10};
n=12;
cn=0;
bestn=0;
bestx=new int[n+1];
x=new int[n+1];
a=new int[n+1][n+1];
for(int h1=1;h1<a.length;h1++){
a[0][h1]=h1;
a[h1][0]=h1;
}
for(int h1=0;h1<c1.length;h1++){
a[c1[h1]][c2[h1]]=1;
a[c2[h1]][c1[h1]]=1;
}
BBClique bb=new BBClique(a);
bestn=bb.bbMaxClique(bestx);
System.out.println("*******優先隊列分支界限法**********");
System.out.println("敵對關系:");
for(int h1=0;h1<c1.length;h1++){
System.out.print(c1[h1]+" vs "+c2[h1]);
System.out.println();
}
System.out.println("隊伍最大人數達: "+bestn);
System.out.print("分別是:");
for(int h4=1;h4<bestx.length;h4++){
if(bestx[h4]==1){
System.out.print(h4+" ");
}
}
}
}