|
Последний раз редактировалось wrest 09.03.2026, 18:14, всего редактировалось 6 раз(а).
Ну то есть, вам нужна функция, на входе у которой то-то а на выходе - то-то. Хорошо, будем считать, что на вход подаётся вектор из подмножеств. Например такой: [[1, 3], [1, 3, 4], [2, 5], [2, 3, 4], [4]]Корректность ввода оставляем за бортом функции. Например что подмножества являются множествами т.е. элементы в подмножествах не повторяются, а также что элементы всех подмножеств принадлежат множеству [1..n] и т.п. Вот функция, которая находит вектор из элементов, удовлетворяющий условию:
{
find_selection(sets) =
my(m, n, i, j, elem, setNum, count, pair, match, adj, found, aug, result, selection, pair_set, pair_elem, seen_set, seen_elem, queue, front, back, prev, u, v, e, s, start_set);
m = #sets;
n = 0;
for(i = 1, m,
for(j = 1, #sets[i],
if(sets[i][j] > n, n = sets[i][j])
)
);
adj = vector(m);
for(i = 1, m, adj[i] = sets[i]);
match = vector(m, i, 0); \\ match[set] = элемент
pair = vector(n, j, 0); \\ pair[elem] = множество
for(start_set = 1, m,
if(match[start_set] == 0,
seen_set = vector(m, i, 0);
seen_elem = vector(n, j, 0);
prev = vector(m + n, i, 0);
queue = vector(m + n);
front = 1; back = 1;
queue[back] = start_set;
back = back + 1;
seen_set[start_set] = 1;
prev[start_set] = -1;
found = 0;
aug = 0;
while(front < back && !found,
v = queue[front];
front = front + 1;
if(v <= m, \\ Это множество
for(k = 1, #adj[v],
e = adj[v][k];
if(e <= n && !seen_elem[e],
seen_elem[e] = 1;
queue[back] = m + e;
back = back + 1;
prev[m + e] = v;
if(pair[e] == 0,
found = 1;
aug = m + e;
break;
);
);
);
, \\ Это элемент (v > m)
e = v - m;
s = pair[e];
if(s != 0 && !seen_set[s],
seen_set[s] = 1;
queue[back] = s;
back = back + 1;
prev[s] = v;
);
);
if(found, break);
);
if(found,
u = aug;
while(1,
v = prev[u];
if(v < 0, break);
if(u > m,
e = u - m;
s = v;
if(s <= m && e <= n && setsearch(Set(adj[s]), e),
match[s] = e;
pair[e] = s;
);
);
u = v;
);
);
);
);
count = 0;
selection = vector(m, i, 0);
for(i = 1, m,
if(match[i] > 0,
if(setsearch(Set(sets[i]), match[i]),
selection[i] = match[i];
count++;
);
)
);
if(count == m,
print("Можно выбрать. Один из вариантов:");
for(i = 1, m,
print("Множество ", i, " (", sets[i], ") -> элемент ", selection[i]);
);
return(selection);
,
print("Невозможно выбрать по одному различному элементу из каждого множества");
return(0);
);
}
Запускаем: Код: ? find_selection([[1,3],[1,3,4],[2,5],[2,3,4],[4]]) Можно выбрать. Один из вариантов: Множество 1 ([1, 3]) -> элемент 1 Множество 2 ([1, 3, 4]) -> элемент 3 Множество 3 ([2, 5]) -> элемент 5 Множество 4 ([2, 3, 4]) -> элемент 2 Множество 5 ([4]) -> элемент 4 cpu time = 1 ms, real time = 2 ms. %6 = [1, 3, 5, 2, 4] Спасибо отправляем в DeepSeek  P.S. Вот другая версия этой функции
find_selection(sets, flag = 0) = {
my(m, n, i, j, elem, setNum, count, pair, match, adj, found, aug, result, selection, pair_set, pair_elem, seen_set, seen_elem, queue, front, back, prev, u, v, e, s, start_set, all_solutions, solutions, temp, used_elem, used_set, current, level, k, stack, indices, valid, solution_count);
m = #sets;
n = 0;
for(i = 1, m,
for(j = 1, #sets[i],
if(sets[i][j] > n, n = sets[i][j])
)
);
adj = vector(m);
for(i = 1, m, adj[i] = sets[i]);
if(flag == 0,
match = vector(m, i, 0);
pair = vector(n, j, 0);
for(start_set = 1, m,
if(match[start_set] == 0,
seen_set = vector(m, i, 0);
seen_elem = vector(n, j, 0);
prev = vector(m + n, i, 0);
queue = vector(m + n);
front = 1; back = 1;
queue[back] = start_set;
back = back + 1;
seen_set[start_set] = 1;
prev[start_set] = -1;
found = 0;
aug = 0;
while(front < back && !found,
v = queue[front];
front = front + 1;
if(v <= m,
for(k = 1, #adj[v],
e = adj[v][k];
if(e <= n && !seen_elem[e],
seen_elem[e] = 1;
queue[back] = m + e;
back = back + 1;
prev[m + e] = v;
if(pair[e] == 0,
found = 1;
aug = m + e;
break;
);
);
);
,
e = v - m;
s = pair[e];
if(s != 0 && !seen_set[s],
seen_set[s] = 1;
queue[back] = s;
back = back + 1;
prev[s] = v;
);
);
if(found, break);
);
if(found,
u = aug;
while(1,
v = prev[u];
if(v < 0, break);
if(u > m,
e = u - m;
s = v;
if(s <= m && e <= n && setsearch(Set(adj[s]), e),
match[s] = e;
pair[e] = s;
);
);
u = v;
);
);
);
);
count = 0;
selection = vector(m, i, 0);
for(i = 1, m,
if(match[i] > 0 && setsearch(Set(sets[i]), match[i]),
selection[i] = match[i];
count++;
)
);
if(count == m,
return(selection);
,
return(0);
);
,
solutions = [];
used_elem = vector(n, j, 0);
current = vector(m, i, 0);
level = 1;
stack = [[1, 0]];
while(#stack > 0,
level = stack[#stack][1];
i = stack[#stack][2] + 1;
if(level > m,
solutions = concat(solutions, [vector(m, j, current[j])]);
stack = stack[1..#stack-1];
next;
);
if(i > #adj[level],
if(current[level] != 0,
used_elem[current[level]] = 0;
current[level] = 0;
);
stack = stack[1..#stack-1];
next;
);
elem = adj[level][i];
if(!used_elem[elem],
if(current[level] != 0,
used_elem[current[level]] = 0;
);
used_elem[elem] = 1;
current[level] = elem;
stack[#stack] = [level, i];
stack = concat(stack, [[level + 1, 0]]);
,
stack[#stack] = [level, i];
);
);
return(solutions);
);
}
Она ничего не печатает только возвращает результат. Плюс, после входных данных можно задать ключ 0- по умлочанию, искать любое решение 1 -искать все решения Запускаем: Код: ? find_selection([[1,3],[1,3,4],[2,5],[2,3,4],[4]]) %9 = [1, 3, 5, 2, 4] ? find_selection([[1,3],[1,3,4],[2,5],[2,3,4],[4]], 1) cpu time = 1 ms, real time = 1 ms. %10 = [[1, 3, 5, 2, 4], [3, 1, 5, 2, 4]] ? Для вашего примера всего решений два. Если решений нет, будет возвращен ноль.
|