子图同构算法
- 如何判定子图同构
- 定义
- 判定方法
- Ullmann算法
- 1.Ullmann算法的定义
- 2.Ullmann算法实现
- 伪代码:
- 步骤:
- 判断同构的代码
如何判定子图同构
定义
有个Gα和Gβ, Gα有pa个点,qa条边,Gβ有pb个点,qb条边。A是Gα的邻接矩阵,相应的B是Gβ的邻接矩阵。Gα中的每一个边和点在Gβ中也有相对应的边和点。那么如何判断同构呢。
判定方法
设A是子图,B是原图。那么有一个A的点到B的点的映射。这个映射的模式叫做M。M是pa行,pb列的。M有一个性质就是每行只有一个1,每列至多一个1。这个就是一个A中的点到B中的点的一个映射。我们定义一个C = [cij] = M(MB)T。如果在图A中i和j有边能推导出图C中i和j有边。那为什么是对的呢。因为M是映射,MB就是把B中被映射的点按照顺序抽出来在和B点对应。 M中第i行j列为1的意义是A的第i个点对应,B的第j个点。MB中第i行j列为1的意义是现在A的第i个点对应到的点到B的第j个点有一条边。把这个矩阵转置在乘以M。C就是B中和A对应的点和在B中的边全部抽出来组成的图。
那么如果aij = 1能推导出cij = 1。A就是B的一个子图的同构。
Ullmann算法
1.Ullmann算法的定义
对于图的同构问题,Ullmann 算法是一个简单的图同构算法,它采取的手段就是利用枚举找到子图同构。
这个算法的目的就是 对于一个给定的图Q,要找出在图G当中的和图Q同构的所有的子图。
2.Ullmann算法实现
伪代码:
步骤:
Step 1 :
建立矩阵。 使得
,如果
Q中第-个顶点与
中第
-个顶点有相同的标签;
Q中第-个顶点的度小于等于
中第
-个顶点的度;
Step 2. 从矩阵生成矩阵
. 即对
进行逐行检查,将部分不为0的元素变成0,使得矩阵
满足每行有且仅有一个元素为1,每列最多只有一个元素不为0.(最大深度为
.)
Step 3 按照以下规则判断矩阵是否满足条件:
MC=M′(M′⋅MB)T, ∀i∀j:(MA[i][j]=1)⇒(MC[i][j]=1).
Step 4 迭代以上步骤,列出所有可能的矩阵.
判断同构的代码
需要输入两个图,以及映射图M,执行step3的步骤
#include<bits/stdc++.h>
using namespace std;
//typedef long long int ll;
const int maxn = 1e5+10;
class Matrix{
public:
int **cont;
//int **du;
int a, b;
public:
Matrix(){
cont = 0;
//du = 0;
a = b = 0;
}
Matrix(int a, int b){
this->a = a;
this->b = b;
cont = new int*[a];
//du = new int*[a];
for (int i = 0; i < a; i++){
cont[i] = new int[b];
// du[i] = new int[b];
for (int j = 0; j < b; j++){
cont[i][j] = 0;
//du[i][j] = 0 ;
}
}
}
Matrix(int *x, int a, int b){
this->a = a;
this->b = b;
cont = new int*[a];
for (int i = 0; i < a; i++){
cont[i] = new int[b];
for (int j = 0; j < b; j++){
cont[i][j] = x[i*a + j];
//cout<<cont[i][j]<<" ";
}
//cout<<endl;
}
}
Matrix(const Matrix& x){
if (x.isNULL()){
cont = 0;
a = b = 0;
}
else{
//x.print();
a = x.a; b = x.b;
//cout<<x.a<<" "<<x.b<<endl;
cont = new int*[a];
for (int i = 0; i < a; i++){
cont[i] = new int[b];
for (int j = 0; j < b; j++){
cont[i][j] = x.cont[i][j];
//cout<<x.cont[i][j]<<" ";
}
//cout<<endl;
}
}
}
~Matrix(){
for (int i = 0; i < b; i++){
delete[] cont[i];
}
delete cont;
}
Matrix Muiltply(Matrix y){
if (isNULL() || y.isNULL() || b != y.a){
return Matrix();
}
Matrix z(a, y.b);
for (int i = 0; i < a; i++){
for (int j = 0; j < y.b; j++){
for (int k = 0; k < b; k++){
z.cont[i][j] += cont[i][k] * y.cont[k][j];
}
}
}
return z;
}
//布尔矩阵乘法
Matrix boolMuiltply(Matrix y){
if (isNULL() || y.isNULL() || b != y.a){
return Matrix();
}
Matrix z(a, y.b);
for (int i = 0; i < a; i++){
for (int j = 0; j < y.b; j++){
for (int k = 0; k < b; k++){
z.cont[i][j] += cont[i][k] * y.cont[k][j];
}
if(z.cont[i][j] > 0){
z.cont[i][j] = 1;
}
}
}
return z;
}
bool isNULL() const{
if (cont == 0){
return true;
}
else{
return false;
}
}
bool isequal(Matrix& y){
if(a == y.a && b == y.b){
for (int i = 0; i < a; i++){
for (int j = 0; j < a; j++){
if(cont[i][j] != y.cont[i][j]){
return false;
}
}
}
return true;
} else{
return false;
}
}
//转置
Matrix Trans(){
Matrix x(b,a);
for (int i = 0; i < a; i++){
for (int j = 0; j < b; j++){
x.cont[j][i] = cont[i][j];
}
}
return x;
}
bool iscontent(const Matrix &A)const{
if(a == A.a && b == A.b){
for (int i = 1; i <= a; i++){
for (int j = 1; j <= b; j++){
if(A.cont[i][j] == 1 && cont[i][j] == 0){
return 0;
}
}
}
return 1;
}
return 0;
}
void print(){
if (isNULL()){
printf("NULL\n");
}
for (int i = 0; i < a; i++){
for (int j = 0; j < b; j++){
cout << cont[i][j] << " ";
}
cout << std::endl;
}
}
};
int main(){
typedef Matrix Map;
typedef Matrix T;
//A为子图,B为原图,M为映射关系
Map A,B;T M;
//根据公式判断
Map x = M.boolMuiltply(M.boolMuiltply(B).Trans());
x.iscontent(A);
}