听起来这是一个应用图算法的好地方。
将人们形成一个图G。对于n个人,图中将有n个节点。如果人i认识人j,则连接节点i和j。
让G的第一次迭代称为G0。通过G进行一次遍历,消除任何认识过多或过少人的人。 (也就是说,如果与i相连的链接数小于5或大于n-5,则消除人i。)
重复此过程,获得G2、G3等最多n(左右)次迭代,获得Gn。剩下在此图中的人就是你应该邀请的人。
每个n次迭代都需要检查n个人与另外n个人,所以算法是O(n^3)。
MATLAB代码可以实现此操作(您没有要求,但我认为它很有趣并且已经编写了)。
N = 10
M = 40
p = 3
q = 3
G = zeros(N);
for k = 1:M
i = randi(N);
j = randi(N);
G(i,j) = 1;
G(j,i) = 1;
end
for i = 1:N
G(i,i) = 0;
end
G_orig = G
invited = ones(1,N);
for k = 1:N
n = sum(invited);
for i = 1:N
people_known = sum(G(i,:));
if invited(i) == 1 && ((people_known < p) || (people_known > n-q))
fprintf('Person %i was eliminated. (He knew %i of the %i invitees.)\n',i,people_known,n);
invited(i) = 0;
G(i,:) = zeros(1,N);
G(:,i) = zeros(1,N);
end
end
end
fprintf('\n\nFinal connection graph')
G
disp 'People to invite:'
invited
disp 'Total invitees:'
n
示例输出(10个人,40个连接,必须认识至少3个人,不能认识至少3个人)
G_orig =
0 0 1 1 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 1
1 0 0 1 1 1 0 0 0 1
1 0 1 0 0 1 0 1 1 0
0 0 1 0 0 0 1 0 1 1
0 1 1 1 0 0 0 1 0 1
0 0 0 0 1 0 0 0 1 0
0 0 0 1 0 1 0 0 0 1
1 0 0 1 1 0 1 0 0 1
0 1 1 0 1 1 0 1 1 0
Person 2 was eliminated. (He knew 2 of the 10 invitees.)
Person 7 was eliminated. (He knew 2 of the 10 invitees.)
Final connection graph
G =
0 0 1 1 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
1 0 0 1 1 1 0 0 0 1
1 0 1 0 0 1 0 1 1 0
0 0 1 0 0 0 0 0 1 1
0 0 1 1 0 0 0 1 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 1 0 0 0 1
1 0 0 1 1 0 0 0 0 1
0 0 1 0 1 1 0 1 1 0
People to invite:
invited =
1 0 1 1 1 1 0 1 1 1
Total invitees:
n =
8