Сформулируйте и докажите теоретически условия существования совершенного паросочетания в двудольном графе (теорема Халла) и предложите алгоритм наивысшей производительности для нахождения максимального паросочетания в крупных двудольных графах; проанализируйте сложность и ограничения на примере распределения студентов по проектам
Формулировка (теорема Холла). Пусть G=(X,Y,E)G=(X,Y,E)G=(X,Y,E) — двудольный граф. Обозначим для множества S⊆XS\subseteq XS⊆X его соседство в YYY как N(S)={y∈Y:∃x∈S, (x,y)∈E}N(S)=\{y\in Y:\exists x\in S,\ (x,y)\in E\}N(S)={y∈Y:∃x∈S,(x,y)∈E}. Тогда в GGG существует паросочетание, насыщающее все вершины XXX (т.е. такое, что каждая вершина из XXX инцидентна некоторому ребру паросочетания) тогда и только тогда, когда ∀S⊆X∣N(S)∣≥∣S∣.
\forall S\subseteq X\quad |N(S)|\ge |S|. ∀S⊆X∣N(S)∣≥∣S∣.
В частном случае ∣X∣=∣Y∣|X|=|Y|∣X∣=∣Y∣ это условие эквивалентно существованию совершенного паросочетания (покрывающего все вершины). Доказательство. 1) Необходимость. Если есть паросочетание, насыщающее XXX, то для любого S⊆XS\subseteq XS⊆X ребра паросочетания инцидентны различным вершинам N(S)N(S)N(S), поэтому ∣N(S)∣≥∣S∣|N(S)|\ge|S|∣N(S)∣≥∣S∣. 2) Достаточность (индукция по ∣X∣|X|∣X∣). Для ∣X∣=0|X|=0∣X∣=0 тривиально. Пусть утверждение верно для всех меньших размеров, и пусть для текущего графа выполнено ∀S⊆X ∣N(S)∣≥∣S∣\forall S\subseteq X\,|N(S)|\ge|S|∀S⊆X∣N(S)∣≥∣S∣. Возьмём произвольный x∈Xx\in Xx∈X и любой y∈N({x})y\in N(\{x\})y∈N({x}). Рассмотрим граф G′G'G′, полученный удалением вершин xxx и yyy. Если в G′G'G′ условие Холла для множества X∖{x}X\setminus\{x\}X∖{x} выполняется, то по индукции существует паросочетание в G′G'G′, насыщающее X∖{x}X\setminus\{x\}X∖{x}, и добавление ребра (x,y)(x,y)(x,y) даёт требуемое паросочетание в GGG. Пусть же в G′G'G′ существует некоторое S⊆X∖{x}S\subseteq X\setminus\{x\}S⊆X∖{x} с ∣NG′(S)∣<∣S∣|N_{G'}(S)|<|S|∣NG′(S)∣<∣S∣. Тогда в исходном графе соседство этого SSS могло увеличиться не более на добавленную вершину yyy, т.е. ∣NG(S∪{x})∣≤∣NG′(S)∣+1<∣S∣+1=∣S∪{x}∣,
|N_G(S\cup\{x\})|\le |N_{G'}(S)|+1 < |S|+1 = |S\cup\{x\}|, ∣NG(S∪{x})∣≤∣NG′(S)∣+1<∣S∣+1=∣S∪{x}∣,
что противоречит условию Холла для множества S∪{x}S\cup\{x\}S∪{x}. Следовательно, такой SSS не существует, и по индукции паросочетание есть. Тем самым доказано достаточное условие. Алгоритм для больших двудольных графов (наивысшая производительность). Для задачи ненаправленного максимального (необязательно совершенного) паросочетания в двудольных графах стандартный быстрый алгоритм — Hopcroft–Karp. Краткая идея алгоритма Hopcroft–Karp: - Поддерживаем текущее паросочетание MMM. - Пока существуют увеличивающие (alternating) пути, выполняем фазу: 1. BFS от всех несвязанных вершин левой доли XXX по ориентированному графу чередующихся рёбер (неиспользуемые ребра слева→справа, используемые ребра справа→слева), строим уровневую структуру и находим длину кратчайших увеличивающих путей. 2. DFS по уровневому графу находит (и добавляет в MMM) максимально возможное множество попарно вершин-непересекающихся кратчайших увеличивающих путей. - Повторяем, пока BFS находит путь до свободной вершины правой доли. Сложность и обоснование: - Пусть n=∣X∣+∣Y∣n=|X|+|Y|n=∣X∣+∣Y∣, m=∣E∣m=|E|m=∣E∣. Одна фаза (BFS+серия DFS) выполняется за O(m)O(m)O(m) при хранении списков смежности. - Количество фаз ограничено O(n)O(\sqrt{n})O(n) (стандартный аргумент: либо длина кратчайшего увеличивающего пути быстро растёт, либо за короткие пути увеличивается размер соответствующего набора пар и в сумме число фаз не превосходит O(n)O(\sqrt{n})O(n)). - Значит общая сложность алгоритма O(n m).
O(\sqrt{n}\,m). O(nm).
Практически для двудольных графов это лучший известный алгоритм по асимптотике для неконструированных (unweighted) задач. Альтернативы: редуцировать задачу к потоку и использовать Dinic/Push–Relabel; для полной двудолицы со взвешиванием применяют венгерский алгоритм (O(n3)O(n^3)O(n3) для полных графов). Применение к распределению студентов по проектам. Сформулируем модель: - Левые вершины XXX — студенты, ∣X∣=ns|X|=n_s∣X∣=ns. - Правые вершины YYY — проекты, ∣Y∣=np|Y|=n_p∣Y∣=np. - Ребро (s,p)∈E(s,p)\in E(s,p)∈E если студент sss допустим или заинтересован в проекте ppp. Случай A (каждый проект — не более одного студента): это стандартное паросочетание; запускаем Hopcroft–Karp с асимптотикой O(n m),n=ns+np, m=∣E∣.
O\big(\sqrt{n}\,m\big),\quad n=n_s+n_p,\ m=|E|. O(nm),n=ns+np,m=∣E∣.
Практические замечания: для nsn_sns порядка 10510^5105 и mmm порядка 10610^6106 алгоритм укладывается в память при использовании компактных списков смежности и работает быстро. Случай B (проекты имеют ёмкости cp≥1c_p\ge1cp≥1): редуцируем к потоку: - Строим сеть: источник →\to→ каждый студент (cap 111), студент→проект (cap 111), проект→сток (cap cpc_pcp). Тогда максимум потока даёт оптимальное распределение. - Для решения используем Dinic или оптимизированный Push–Relabel; практическая сложность выше, но для разреженных графов масштабируемо. Если все cpc_pcp малы, можно также «размножить» вершины проектов в cpc_pcp копий и применить Hopcroft–Karp (эффективно при суммарном числе копий не очень большом). Ограничения и практические проблемы: - Память: хранение mmm рёбер требует O(m)O(m)O(m) памяти — критично при mmm десятки/сотни миллионов. - Критические случаи: очень высокий максимум степени (горячие проекты) влияет на баланс и кэш-производительность. - Дополнительные ограничения (приоритеты студентов, нижние квоты проектов, взаимные предпочтения, стабильность) требуют иных формулировок: стабильное распределение — алгоритм Гейла–Шепли, нижние/верхние квоты — потоки с нижними ограничениями, оптимизация по весам — задача назначений (венгер) или min-cost-flow. - Для динамических или распределённых задач возможны эвристики/приближённые алгоритмы (жадный, многократный локальный поиск) и параллельные реализации Hopcroft–Karp / Dinic. Рекомендации на практике: - Если каждый проект — одно место: использовать Hopcroft–Karp (реализация с adjacency lists). - Если проекты имеют большой/разный capacity: построить сеть и запускать Dinic/Push–Relabel; при малых суммарных ёмкостях — клонить вершины и Hopcroft–Karp. - Для очень больших и динамиčnih систем — предварительный жадный подбор + последующая оптимизация Hopcroft–Karp/Dinic, и/или распределённые/параллельные реализации. Если хотите, могу дать компактный псевдокод Hopcroft–Karp и/или схему преобразования с ёмкостями для конкретных чисел ns,np,mn_s,n_p,mns,np,m.
∀S⊆X∣N(S)∣≥∣S∣. \forall S\subseteq X\quad |N(S)|\ge |S|.
∀S⊆X∣N(S)∣≥∣S∣. В частном случае ∣X∣=∣Y∣|X|=|Y|∣X∣=∣Y∣ это условие эквивалентно существованию совершенного паросочетания (покрывающего все вершины).
Доказательство.
1) Необходимость. Если есть паросочетание, насыщающее XXX, то для любого S⊆XS\subseteq XS⊆X ребра паросочетания инцидентны различным вершинам N(S)N(S)N(S), поэтому ∣N(S)∣≥∣S∣|N(S)|\ge|S|∣N(S)∣≥∣S∣.
2) Достаточность (индукция по ∣X∣|X|∣X∣). Для ∣X∣=0|X|=0∣X∣=0 тривиально. Пусть утверждение верно для всех меньших размеров, и пусть для текущего графа выполнено ∀S⊆X ∣N(S)∣≥∣S∣\forall S\subseteq X\,|N(S)|\ge|S|∀S⊆X∣N(S)∣≥∣S∣. Возьмём произвольный x∈Xx\in Xx∈X и любой y∈N({x})y\in N(\{x\})y∈N({x}). Рассмотрим граф G′G'G′, полученный удалением вершин xxx и yyy. Если в G′G'G′ условие Холла для множества X∖{x}X\setminus\{x\}X∖{x} выполняется, то по индукции существует паросочетание в G′G'G′, насыщающее X∖{x}X\setminus\{x\}X∖{x}, и добавление ребра (x,y)(x,y)(x,y) даёт требуемое паросочетание в GGG.
Пусть же в G′G'G′ существует некоторое S⊆X∖{x}S\subseteq X\setminus\{x\}S⊆X∖{x} с ∣NG′(S)∣<∣S∣|N_{G'}(S)|<|S|∣NG′ (S)∣<∣S∣. Тогда в исходном графе соседство этого SSS могло увеличиться не более на добавленную вершину yyy, т.е.
∣NG(S∪{x})∣≤∣NG′(S)∣+1<∣S∣+1=∣S∪{x}∣, |N_G(S\cup\{x\})|\le |N_{G'}(S)|+1 < |S|+1 = |S\cup\{x\}|,
∣NG (S∪{x})∣≤∣NG′ (S)∣+1<∣S∣+1=∣S∪{x}∣, что противоречит условию Холла для множества S∪{x}S\cup\{x\}S∪{x}. Следовательно, такой SSS не существует, и по индукции паросочетание есть. Тем самым доказано достаточное условие.
Алгоритм для больших двудольных графов (наивысшая производительность). Для задачи ненаправленного максимального (необязательно совершенного) паросочетания в двудольных графах стандартный быстрый алгоритм — Hopcroft–Karp.
Краткая идея алгоритма Hopcroft–Karp:
- Поддерживаем текущее паросочетание MMM.
- Пока существуют увеличивающие (alternating) пути, выполняем фазу:
1. BFS от всех несвязанных вершин левой доли XXX по ориентированному графу чередующихся рёбер (неиспользуемые ребра слева→справа, используемые ребра справа→слева), строим уровневую структуру и находим длину кратчайших увеличивающих путей.
2. DFS по уровневому графу находит (и добавляет в MMM) максимально возможное множество попарно вершин-непересекающихся кратчайших увеличивающих путей.
- Повторяем, пока BFS находит путь до свободной вершины правой доли.
Сложность и обоснование:
- Пусть n=∣X∣+∣Y∣n=|X|+|Y|n=∣X∣+∣Y∣, m=∣E∣m=|E|m=∣E∣. Одна фаза (BFS+серия DFS) выполняется за O(m)O(m)O(m) при хранении списков смежности.
- Количество фаз ограничено O(n)O(\sqrt{n})O(n ) (стандартный аргумент: либо длина кратчайшего увеличивающего пути быстро растёт, либо за короткие пути увеличивается размер соответствующего набора пар и в сумме число фаз не превосходит O(n)O(\sqrt{n})O(n )).
- Значит общая сложность алгоритма
O(n m). O(\sqrt{n}\,m).
O(n m). Практически для двудольных графов это лучший известный алгоритм по асимптотике для неконструированных (unweighted) задач. Альтернативы: редуцировать задачу к потоку и использовать Dinic/Push–Relabel; для полной двудолицы со взвешиванием применяют венгерский алгоритм (O(n3)O(n^3)O(n3) для полных графов).
Применение к распределению студентов по проектам.
Сформулируем модель:
- Левые вершины XXX — студенты, ∣X∣=ns|X|=n_s∣X∣=ns .
- Правые вершины YYY — проекты, ∣Y∣=np|Y|=n_p∣Y∣=np .
- Ребро (s,p)∈E(s,p)\in E(s,p)∈E если студент sss допустим или заинтересован в проекте ppp.
Случай A (каждый проект — не более одного студента): это стандартное паросочетание; запускаем Hopcroft–Karp с асимптотикой
O(n m),n=ns+np, m=∣E∣. O\big(\sqrt{n}\,m\big),\quad n=n_s+n_p,\ m=|E|.
O(n m),n=ns +np , m=∣E∣. Практические замечания: для nsn_sns порядка 10510^5105 и mmm порядка 10610^6106 алгоритм укладывается в память при использовании компактных списков смежности и работает быстро.
Случай B (проекты имеют ёмкости cp≥1c_p\ge1cp ≥1): редуцируем к потоку:
- Строим сеть: источник →\to→ каждый студент (cap 111), студент→проект (cap 111), проект→сток (cap cpc_pcp ). Тогда максимум потока даёт оптимальное распределение.
- Для решения используем Dinic или оптимизированный Push–Relabel; практическая сложность выше, но для разреженных графов масштабируемо. Если все cpc_pcp малы, можно также «размножить» вершины проектов в cpc_pcp копий и применить Hopcroft–Karp (эффективно при суммарном числе копий не очень большом).
Ограничения и практические проблемы:
- Память: хранение mmm рёбер требует O(m)O(m)O(m) памяти — критично при mmm десятки/сотни миллионов.
- Критические случаи: очень высокий максимум степени (горячие проекты) влияет на баланс и кэш-производительность.
- Дополнительные ограничения (приоритеты студентов, нижние квоты проектов, взаимные предпочтения, стабильность) требуют иных формулировок: стабильное распределение — алгоритм Гейла–Шепли, нижние/верхние квоты — потоки с нижними ограничениями, оптимизация по весам — задача назначений (венгер) или min-cost-flow.
- Для динамических или распределённых задач возможны эвристики/приближённые алгоритмы (жадный, многократный локальный поиск) и параллельные реализации Hopcroft–Karp / Dinic.
Рекомендации на практике:
- Если каждый проект — одно место: использовать Hopcroft–Karp (реализация с adjacency lists).
- Если проекты имеют большой/разный capacity: построить сеть и запускать Dinic/Push–Relabel; при малых суммарных ёмкостях — клонить вершины и Hopcroft–Karp.
- Для очень больших и динамиčnih систем — предварительный жадный подбор + последующая оптимизация Hopcroft–Karp/Dinic, и/или распределённые/параллельные реализации.
Если хотите, могу дать компактный псевдокод Hopcroft–Karp и/или схему преобразования с ёмкостями для конкретных чисел ns,np,mn_s,n_p,mns ,np ,m.