您的位置:首页 > 其它

无向图的最大割问题的实现

2015-05-07 23:57 148 查看
问题描述:

什么是无向图的最大割?

有无向图G=(V,E).设U是V的一个子集。对任意的顶点u,v如果(u,v)是E中的一条边,如果u在U中,则v一定不

在U中,这样的边称为顶点集合U的一个割边。那个这个顶点集合U所有的割边就构成图G的一个割。最大割

的意思,就是说含割边最多的割。

编程任务:

给定一个无向图G,计算G的最大割。

数据输入:

第一行2个整数 n,e表示顶点个数和边个数。下面e行是边,每行2个整数对应顶点编号。顶点编号从1-n;

数据输出:

第一行是最大割的边数。

第二行是顶点集的向量对应1-n,0表示不在集合,1表示在集合。

解题思想:

这道题也是一个子集选取问题,所以它的解空间树是一个子集树。这个集合n个元素,每个元素可以有

选取或不选取2种选择,所以共用2^n个子集。

这里用分支界限法。

分支界限法:类似宽度优先搜索,它和回溯的区别在与,它每次都取一个节点,然后把它的所有的儿子节点

都扩展,然后加到队列中,所以说,分支界限法,这种扩展方式导致没个节点最多一次扩展机会,它在扩展

它的分支的时候,根据一定的界限条件,或淘汰不可能产生最优解的分支。

这里的队列有2种,一种是普通队列就是先进先出。

另一种就是优先级队列,它会根据优先级进行出队,这和Windows中的消息队列类似。

在C++中,STL中priority_queue就是优先级队列。queue是普通队列。优先级队列可以用最大堆或最小堆

实现。

#include <iostream>

#include <queue>

using namespace std;

int n,e;//顶点数和边数

int Graph[200][200];//存储图的邻接矩阵

int bestcut = 0;//存储最优解

int bestx[200];//存储最优解

struct HeapNode//队列节点

{

HeapNode()

{

memset(x,0,sizeof(x));

}

int i;

int cut;

int edges;

int x[200];

booloperator < (const HeapNode&a)const

{

returncut<a.cut;

}

};

void maxcut()

{

HeapNodeE;

priority_queue<HeapNode> Q;

E.cut = 0;

E.edges = e;

E.i = 0;

while (1)

{

if (E.i==n)

{

if (E.cut>bestcut)

{

bestcut = E.cut;

memcpy(bestx,E.x,sizeof(int)*n);

}

}

else

{

HeapNodetemp = E;

int i =E.i;

for (intj=0;j<n;j++)

{

if (Graph[i][j])

{

if (temp.x[j])

{

temp.cut--;

}

else

{

temp.cut++;

temp.edges--;

}

}

}

temp.x[i] =1;

temp.i++;

Q.push(temp);

if(E.cut+E.edges>bestcut)//界限条件

{

E.i++;

Q.push(E);

}

}

if(Q.size()==0)//队列为空跳出循环

{

break;

}

E = Q.top();

Q.pop();

}

}

int main()

{

intu,v;

cin>>n>>e;

for (int i=0;i<e;i++)

{

cin>>u>>v;

Graph[u-1][v-1] = 1;

Graph[v-1][u-1] = 1;

}

maxcut();

cout<<bestcut<<endl;

for (int k=0;k<n;k++)

{

cout<<bestx[k]<<'';

}

cout<<endl;

return 0;

}

输入实例

7 18

1 4

1 5

1 6

1 7

2 3

2 4

2 5

2 6

2 7

3 4

3 5

3 6

3 7

4 5

4 6

5 6

5 7

6 7

输出实例:

12

1 1 1 0 1 0 0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: