Back, graph theory - the biggest problem group (seeking the most complete subgraph)

 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.测试结果

 

发布了57 篇原创文章 · 获赞 9 · 访问量 3611

Guess you like

Origin blog.csdn.net/Jayphone17/article/details/102962990
Recommended