关于一个应用分枝界限法解决最小顶点覆盖问题的程序说明

 

//程序下载自:http://download.csdn.net/source/1930594

//头文件Minheap.h

 

template <class Type>

class MinHeap                                        //最小堆类;

{

public:                             

MinHeap(Type a[], int n);                          //带两参数的构造函数,在此程序中没有应用;

MinHeap(int ms);                                      //构造函数重载,只初始化堆的大小,对堆中结点不初始化;另外,堆元素的存储是以数组

~MinHeap();                                             //形式,且无父、子指针,访问父亲结点,利用数组标号进行;

bool Insert(const Type &x);                       //插入堆中一个元素;

bool RemoveMin(Type &x);                          //删除堆顶最小结点;

void MakeEmpty();                                              //使堆为空

bool IsEmpty();

bool IsFull();

int Size();

protected:

void FilterDown(const int start, const int endOfHeap);                                  / /自顶向下构造堆

void FilterUp(const int start);                                                                        //自底向上构造堆

private:

Type *heap;                                                                 

int maxSize;

const int defaultSize;

int currentSize;                                                                                           //堆当前结点个数大小

};

 

template <class Type>

MinHeap<Type>::MinHeap(int ms):defaultSize(100)

{

maxSize=ms>defaultSize ? ms : defaultSize;

heap=new Type[maxSize];

currentSize=0;

}

 

template <class Type>

MinHeap<Type>::MinHeap(Type a[], int n):defaultSize(100)

{

maxSize=n>defaultSize ? n : defaultSize;

heap=new Type[maxSize];

currentSize=n;

for (int i=0; i<n; i++) heap[i]=a[i];

int curPos=(currentSize-2)/2;

while (curPos>=0)

{

   FilterDown(curPos, currentSize-1);

   curPos–;

}

}

 

template <class Type>

MinHeap<Type>::~MinHeap()

{

delete []heap;

}

 

template <class Type>

void MinHeap<Type>::FilterDown(const int start, const int endOfHeap)

{

int i=start, j=i*2+1;

Type temp=heap[i];

while (j<=endOfHeap)

{

   if (j<endOfHeap&&heap[j]>heap[j+1]) j++;                            

   if (temp<heap[j]) break;                        

   else

   {

    heap[i]=heap[j];

    i=j;

    j=2*i+1;

   }

}

heap[i]=temp;

}

 

template <class Type>

void MinHeap<Type>::FilterUp(const int start)

{

int i=start, j=(i-1)/2;

Type temp=heap[i];

while (i>0)

{

   if (temp>=heap[j]) break;

   else

   {

    heap[i]=heap[j];

    i=j;

    j=(i-1)/2;

   }

}

heap[i]=temp;

}

 

template <class Type>

bool MinHeap<Type>::RemoveMin(Type &x)

{

if (IsEmpty())

{

   cerr<<“Heap empty!”<<endl;

   return false;

}

x=heap[0];

heap[0]=heap[currentSize-1];

currentSize–;

FilterDown(0, currentSize-1);

return true;

}

 

template <class Type>

bool MinHeap<Type>::Insert(const Type &x)

{

if (IsFull())

{

   cerr<<“Heap Full!”<<endl;

        return false;

}

heap[currentSize]=x;

FilterUp(currentSize);

currentSize++;

return true;

}

 

template <class Type>

bool MinHeap<Type>::IsEmpty()

{

return currentSize==0;

}

 

template <class Type>

bool MinHeap<Type>::IsFull()

{

return currentSize==maxSize;

}

 

template <class Type>

void MinHeap<Type>::MakeEmpty()

{

currentSize=0;

}

 

template <class Type>

int MinHeap<Type>::Size()

{

return currentSize;

}

//MinCover.cpp #include<iostream.h> #include<fstream.h> #include”MinHeap.h” int *p; //最小堆结点 class HeapNode                                                                 //堆结点类; { friend class VC; public: operator int()const{return cn;}                                       //重载运算符,比较两个结点; private:    int i,cn,*x,*c;                                                          //i标示堆中结点号,cn标示当前加入的覆盖顶点中权重之和,x数组标示那些                                                                                          //顶点加入了覆盖顶点的行列,c数组标示X中的覆盖顶点中所有的邻接                                                                                            // 顶点;                                                                                         }; class VC                                                              // VC类用来对堆中结点内部的的操作, { friend MinCover(int **,int [],int);                           private: void BBVC(); bool cover(HeapNode E); void AddLiveNode(MinHeap<HeapNode>&H,HeapNode E,int cn,int i,bool ch); int **a,n,*w,*bestx,bestn; }; void VC::BBVC() { MinHeap<HeapNode>H(100000);   //建立初始空堆; HeapNode E; E.x=new int[n+1]; E.c=new int[n+1]; for(int j=1;j<=n;j++) {    E.x[j]=E.c[j]=0; } int i=1,cn=0;  //开始时; while(true) {    if(i>n)    {     if(cover(E))     {      for(int j=1;j<=n;j++)       bestx[j]=E.x[j];      bestn=cn;      break;     }    }    else    {     if(!cover(E))      AddLiveNode(H,E,cn,i,true);                  //加入结点标号为i 的结点到顶点覆盖集中,并把更新后的结点再插入堆中;     AddLiveNode(H,E,cn,i,false);                  //不把结点标号为 i 的结点加入到顶点覆盖集中,并把更新后的结点插入堆中;    }    if(H.IsEmpty())break;    H.RemoveMin(E);                                   //把 堆顶点先移除给E;     cn=E.cn;    i=E.i+1;                                                         } } //cover bool VC::cover(HeapNode E) { for(int j=1;j<=n;j++) {    if(E.x[j]==0&&E.c[j]==0)     return false;        //存在任意一条边的两个顶点都为0的情况下,为未覆盖情况;X[j]记录覆盖顶点,c[j]记录与覆盖顶点相连的顶点; }                             //0表征未覆盖,1表征已覆盖; return true; } void VC::AddLiveNode(MinHeap<HeapNode> &H,HeapNode E,int cn,int i,bool ch) { HeapNode N; N.x=new int[n+1]; N.c=new int[n+1]; for(int j=1;j<=n;j++) {    N.x[j]=E.x[j];    N.c[j]=E.c[j]; } N.x[i]=ch?1:0; if(ch) {    N.cn=cn+w[i];                                                     / /记录I顶点是否加入覆盖的行列中;    for(int j=1;j<=n;j++)     if(a[i][j]>0)                                                        //如果i,j相邻,刚把j顶点加入覆盖邻接顶点集中;      N.c[j]++;                                                           } else  {    N.cn=cn; } N.i=i; H.Insert(N);                   }                int MinCover(int **a,int v[],int n) { VC Y; Y.w=new int[n+1]; for(int j=1;j<=n;j++) {    Y.w[j]=v[j];       //初始化VC类对象Y; } Y.a=a;  Y.n=n; Y.bestx=v;        //将地址赋予bestx, Y.BBVC(); return Y.bestn;      //bestn是最后的最小顶点覆盖集权重; }                   int main() { int u,v; int n,c; ifstream infile(“input.txt”); if(!infile) {    cout<<“Can’t open input.txt”<<endl;    return 0; } ofstream outfile(“output.txt”); if(!outfile) {    cout<<“Can’t open output.txt”<<endl;    return 0; } infile>>n>>c; //Make2DArray(a,n+1,n+1); int **a; a=new int *[n+1]; for(int k=0;k<=n;k++)    a[k]=new int[n+1]; for(int i=0;i<=n;i++)    for(int j=0;j<=n;j++)     a[i][i]=0; p=new int[n+1]; for(i=1;i<=n;i++)    infile>>p[i]; for(i=1;i<=c;i++) {    infile>>u>>v;    a[u][v]=1;    a[v][u]=1; } cout<<MinCover(a,p,n)<<endl; for(i=1;i<=n;i++)    cout<<p[i]<<” “; cout<<endl; return 0; } ‘input.txt’ 7 7 1 100 1 1 1 100 10 1 6 2 4 2 5 3 6 4 5  4 6 6 7 说明:在文章中,顶点与结点是两个不同的概念,结点中有记录当前加入顶点覆盖集的 i,有加入顶点覆盖集中的x[],有加入与顶点覆盖集邻接的c[]顶点集; 此程序的运行流程:首先是初始建最小堆过程,把每个顶点插入到堆中,在每个顶点的内部,X[]数组就是记录此时的顶点覆盖集,然后选取此结点内部顶点覆盖集权重之和cn最小的顶点做为扩展结点,然后以比此顶点标号大1的结点为参考(i = E.i + 1),分别插入两个结点到堆中,一个是 i 顶点加入顶点覆盖集后的结点,一个是 i顶点没有加入顶点覆盖集后的结点,然后重新建堆,再重新移出堆结点,重复如此,直到所有顶点都被标记进x[]或c[]中()。

 

    原文作者:分支限界法
    原文地址: https://blog.csdn.net/zhshow/article/details/5481370
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞