1. Analysis
To solve the biggest problem group, which is seeking the most complete subgraph. We need to understand the concepts, now have the following figure:
(1) Complete Ko图:
Given an undirected graph G = (V, E), where V is the set of vertices, E is the set of edges. G '= (V', E ') if the vertex set V'∈V, E'∈E, and G' of any of the two points are connected with a side, called G 'is a subgraph of G completely. FIG example, the following are a few complete subgraph on the map:
(2) Group:
Complete subgraph of G is a group G if and only if G 'is not included in a larger holon in graph G, i.e. G' is a great complete subgraph of G. For example in FIG. (C), (D) a group G, and (a) (b) G group is not, because they contain a larger holon in graph G in (c).
(3) the largest group:
The largest group G, G refers to all groups, the group containing the largest number of vertices, for example (D) is the largest group.
2. Algorithm Design
(1) Constraints:
Biggest problem solution space group comprising 2 ^ n subsets, there is a case of a set of two nodes not connected edges of these subsets. Obviously sister feasible solution might not be a problem in this case, so you need to set constraints to determine whether there has been the problem could lead to a feasible solution.
Suppose now extended to t junction layer, the 1 ~ t-1 nodes state (whether in the regiment) has been determined. Subsequently extended along the left branch of the extension point, this case needs to be determined whether t junction into regiment. It is determined whether the nodes t 1 ~ t-1 and the nodes are connected to the selected node has connected to it into the regiment, x [t] = 1, or not into the regiment, x [t] = 0. As shown in FIG:
(2) delimiting conditions (pruning function):
假设当前的扩展结点为z,如果z处于第t层,前面1~t-1 层的结点的状态已经确定了。接下来确定t结点的状态。前t个结点状态确定当前已放团内的结点个数(用cn表示),假设t+1 ~ n 的所有结点都放进团,用fn表示,且fn=n-t ,则cn+fn是所有从根出发的路径中经过中间结点z的可行解所包含结点个数的上界。
如果fn+cn小于等于当前最优解bestn,则说明不再需要从中间结点z继续像子孙结点搜索。因此,限界条件可以描述为:cn+fn>bestn。
(3)搜索过程:
从根节点开始,以深度游戏按的方式进行。每次搜索到一个结点,判断约束条件,看是否可以将当前结点加入到团中。如果可以,则沿着当前结点左分支继续向下搜索,如果不可以,判断戒指函数,如果满足则沿着当前结点的右分支继续向下搜索。
3.源代码
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; const int N=111; //设置矩阵的大小 int graph[N][N]; //用邻接矩阵存储图 bool x[N]; //是否将i个顶点加入团中 bool bestx[N]; //记录最优已经放入团中的顶点 int bestn; //记录最优值 int cn; //已经放入团中的结点数 int n;//顶点个数 int m; //边的个数 bool place(int t) //判断是否能放进团中 { bool OK =true; for (int j=1;j<t;j++) //判断目前扩展的t顶点和前面t-1个顶点是否相连。 { if(x[j] && graph[t][j]==0) //如果不相连 { OK=false; //返回false break; } } return OK; //如果相连。返回true } void backtrack(int t) //回溯,递推 { if(t>n) //当到达叶子结点 { for(int i=1;i<=n;i++) { bestx[i]=x[i]; //记录最优值结点号 } bestn=cn; //记录最优值 return; } if(place(t)) //如果能放进团中 { x[t]=1;//标为1 cn++; //个数+1 backtrack(t+1); //向下递推 cn--; //向上回溯 } if(cn+n-t>bestn) //限界条件,进入右子树,不能加入团中。 { x[t]=0; //不能放入团中,标为0 backtrack(t+1); //向下递推。 } } int main() { int u; //结点1 int v; //结点2 cout << "请输入结点的个数n;"<< endl; cin >> n; cout << "请输入边数m:"<< endl; cin >>m; memset(graph,0,sizeof(graph)); cout <<"请输入有边相连的两个顶点u和v:"<< endl; for (int i=1;i<=m;i++) { cin >> u>> v; graph[u][v]=1; graph[v][u]=1; } bestn=0; cn=0; backtrack(1); cout << "最大团的结点个数有:"<< bestn << endl; cout << "结点有:"<< endl; for (int i=1;i<=n;i++) { if(bestx[i]) { cout << i << " "; //输出的是结点号 } } return 0; }
4.测试结果