给出一个平面n向无向图,其中n个点用整数[1,2,.. n]标记
任务是通过“唯一”找到所有唯一的四边形,我们的意思是:如果两个四边形的所有四个点都相同,但是相对顺序不同,则将这两个视为“相同”四边形。例如,[1,2,3,4]和[1,3,2,4]是相同的四边形。
输入:可以按您喜欢的任何格式存储图形。这里我们使用相邻矩阵(对于无向图,在下面的描述中,每个物理边均输入一次),第一行中的前两个数字分别是顶点数和边数。然后,以下各行每次都输入每个边缘。
输出:4乘M矩阵或数组列表。 M是您找到的最后一个唯一的四边形计数。
在以下五个点的无向完整图中:
5 10
1 4
1 2
1 3
1 5
2 3
2 4
2 5
3 4
3 5
4 5
只有五个唯一的四边形(忽略顶点序列的相对顺序):
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
我现在没有完美的解决方案。
以下MATLAB解决方案只能为Case-1找到每个唯一的四边形,但在Case-2中失败,即找不到四边形。
%% Count Quadrangles
clc;
v = vertex(:,1);
t = vertex(:,2);
G = zeros( max(max(v),max(t)));
n = length(G);
% For muilt-edge graph , Build the matrix for graph:
for i = 1:length(v)
G(v(i), t(i)) = G(v(i), t(i)) + 1;
G(t(i), v(i)) = G(v(i), t(i));
end
issymmetric(G)
max(max(G))
% For single edge graph, Build the matrix for graph:
% G(sub2ind(size(G),v, t))=1;
% G(sub2ind(size(G),t, v))=1; % fill the symmetric position
tic
quad_cnt = 0;
% G_ = graph(G);
quad_points = [];
%% O(N^3)
for i = 1:n
for j = i+1:n
if (j==i || G(i,j)==0)
continue;
end
for k = j+1:n
if ( k==i || k==j || (G(k,i)==0 && G(k,j) == 0) )
continue;
end
for p = k+1:n
if ( p==i || p==j || p==k || G(p,i)==0 || G(p,k) == 0)
continue;
end
% otherwise, a quadrangle is ofund
quad_cnt = quad_cnt+1;
% save the vertices
quad_points(quad_cnt,:) = [i,j,k,p];
end
end
end
end
toc
% 0.1571 sec
quad_cnt
% output each triangle:
quad_points
%% O(deg*(V^2))
测试用例 通过使用顶点索引进行边输入(注意:从“ 1”开始而不是“ 0”):
情况1: 输入:
5 10
1 4
1 2
1 3
1 5
2 3
2 4
2 5
3 4
3 5
4 5
输出:
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
情况2: 输入:
8 8
1 3
2 3
1 4
2 4
1 8
2 5
3 6
4 7
输出:
1 2 3 4
答案 0 :(得分:0)
我还有另一种方法来查找四边形。它使用DFS的概念。遍历所有节点的图以找到特定深度的四边形。要删除重复项,请对四边形进行排序,然后删除四边形或使用哈希表。我的c ++实现如下:
#include<bits/stdc++.h>
using namespace std;
// if Edge[a][b] = 1, then there is an edge between node 'a' and 'b'
int Edge[100][100] = {0};
// to keep the list of quadrangles
// here 'set' is a data structure that keep unique elements
set< vector<int> > quadrangles;
// forbiddenNode[n] = 1, if this node 'n' is forbidden to visit
// forbiddenNode[n] = 0, if this node 'n' is not forbidden to visit
int forbiddenNode[100]={0};
// taken[n] = 1, if this node 'n' is taken in current Quadrangles
// taken[n] = 0, if this node 'n' is not taken in current Quadrangles
int taken[1000]={0};
void AddQuadrangle(vector<int> q) {
sort(q.begin(), q.end());
quadrangles.insert(q);
}
void findQuadrangles(int curNode, int depth, vector<int> &curQuadrangles, int numOfNodes) {
if(depth == 0) {
if( Edge[curNode][curQuadrangles[0]] == 1) {
// found a quadrangle
AddQuadrangle(curQuadrangles);
}
}
for(int i = 1; i <= numOfNodes; i++) {
if(forbiddenNode[i] == 0 && taken[i] == 0 && Edge[curNode][i] == 1) {
// take this node
taken[i] = 1;
// add this node to curQuadrangles in the back
curQuadrangles.push_back(i);
findQuadrangles(i, depth - 1, curQuadrangles, numOfNodes);
// undo take this node
taken[i] = 0;
// remove this node to curQuadrangles from the back
curQuadrangles.pop_back();
}
}
}
int main() {
int numOfNodes, numOfEdge;
// take input for number of nodes, edges
scanf("%d %d", &numOfNodes, &numOfEdge);
// take input for edges
for(int i=0; i < numOfEdge; i++) {
int x, y;
scanf("%d %d",&x, &y);
Edge[x][y] = 1;
Edge[y][x] = 1;
}
for(int i = 1; i <= numOfNodes; i++) {
vector<int> curQuadrangle;
curQuadrangle.push_back(i);
taken[i] = 1;
findQuadrangles(i, 3, curQuadrangle, numOfNodes);
// set this node as forbidden to include in any quadrangle
forbiddenNode[i];
}
// print quadrangles
for( set<vector<int> >::iterator it = quadrangles.begin(); it != quadrangles.end(); it++) {
vector<int> q = *it;
printf("%d %d %d %d\n",q[0], q[1], q[2], q[3]);
}
return 0;
}
答案 1 :(得分:0)
这是我更新的MATLAB代码,可以正常工作(欢迎您测试我的代码,看看它在任何特殊图形上是否失败):
clc;
v = vertex(:,1);
t = vertex(:,2);
G = zeros( max(max(v),max(t)));
n = length(G);
% For multi-edge graph , Build the matrix for graph:
for i = 1:length(v)
G(v(i), t(i)) = G(v(i), t(i)) + 1;
G(t(i), v(i)) = G(v(i), t(i)); % comment here is input is bi-directional
end
quad_cnt = 0;
quad_points = [];
for i = 1:n
for j = i+1:n
if (j==i || G(j,i)==0)
continue;
end
for k = i+1:n
if ( k==i || k==j || (G(k,i)==0 && G(k,j)==0))
continue;
end
if (G(k,i)~=0 && G(k,j)~=0)
for p = i+1:n
if ( p==i || p==j || p==k)
continue;
end
if (G(p,i)~=0 && G(p,j)~=0)||(G(p,i)~=0 && G(p,k)~=0)||(G(p,j)~=0 && G(p,k)~=0)
quad_cnt = quad_cnt+1;
quad_points(quad_cnt,:) = [i,j,k,p];
end
end
end
if (G(k,i)==0 && G(k,j)~=0)
for p = i+1:n
if (p==i || p==j || p==k || G(p,k)==0 || G(p,i) == 0)
continue;
end
quad_cnt = quad_cnt+1;
quad_points(quad_cnt,:) = [i,j,k,p];
end
end
if (G(k,i)~=0 && G(k,j)==0)
for p = i+1:n
if ( p==i || p==j || p==k || G(p,j)==0 || G(p,k) == 0)
continue;
end
quad_cnt = quad_cnt+1;
quad_points(quad_cnt,:) = [i,j,k,p];
end
end
end
end
end
% quad_cnt
% Remove repeat
% 1) sort
hash = [];
Base = max(max(v),max(t))+ 1;
for i =1: quad_cnt
temp = sort(quad_points(i,:));
quad_points(i,:) = temp;
hash(i) = quad_points(i,1)*Base^3 + quad_points(i,2)*Base^2 + quad_points(i,3)*Base + quad_points(i,4);
end
% 2) remove repeats
[C, ~, ~] = unique(hash);
quad_cnt = length(C);
quad_cnt
quad_points = [];
for i = 1: quad_cnt
num = C(i);
digit = [];
for k = 1:4
digit(k) = mod(num, Base);
num = fix(num/Base); % or use "floor()"
end
quad_points(i,:) = digit;
end
% output each quadrangle:
quad_points;