是麼時二分圖
這個圖的節點可以被分為兩個集合, 使得同一集合內沒有連邊。
匈牙利演算法
例題
IOI 有 $m$ 道題, HPY 會 $n$ 個演算法, 一共有 $k$ 個演算法可以解決IOI題。
HPY 會的演算法太多了, 所有這次 IOI 用了這個演算法, 等到下一次 IOI 時才會記其這個演算法。
<h1 id="constraints">輸入</h1>
第一行輸入三個整數$ n $、$ m $和$ k $:HPY會的演算法的數量、IOI題目的數量和可以解決題目的數量。HPY會的演算法編號為$ 1,2,\dots,n $,IOI題目編號為$ 1,2,\dots,m $。
之後有$ k $行描述用演算法可以解決的問題。每行有兩個整數$ a $和$ b $:演算法$ a $可以解決 IOI 的 $ b $ 號問題。
<h1 id="constraints">輸出</h1>
首先列印一個整數$ r $:最大解決IOI題目數量。之後,列印$ r $行描述解決的題目。你可以列印任何有效的解決方案。
<h1 id="constraints">約束</h1>
<ul>
<li><span class="math inline">$ 1 \le n,m \le 500 $</span></li>
<li><span class="math inline">$ 1 \le k \le 1000 $</span></li>
<li><span class="math inline">$ 1 \le a \le n $</span></li>
<li><span class="math inline">$ 1 \le b \le m $</span></li>
</ul>
<h1 id="example">示例</h1>
<table class="vjudge_sample">
<thead>
<tr>
<th>Input</th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr>
<td><pre>3 2 4
1 1
1 2
2 1
3 1
</pre></td>
<td><pre>2
1 2
3 1
</pre></td>
</tr>
</tbody>
</table>
</div>
對於一個點, 如果它沒有匹配, 找它能匹配的點, 如果可以沒有匹配或者可以換一個匹配就可以
#include<bits/stdc++.h>
using namespace std;
const int N = 505;
vector<int>g[N];
int vis[N], n, m, q, u, v, ans, p[N];
bool dfs(int x){
if(vis[x]){
return 0;
}
vis[x] = 1;
for(auto v : g[x]){
if((!p[v] || dfs(p[v]))){
p[v] = x;
return 1;
}
}
return 0;
}
int main(){
cin >> n >> m >> q;
while(q--){
cin >> u >> v;
g[u].push_back(v);
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
vis[j] = 0;
}
ans += dfs(i);
}
cout << ans << '\n';
for(int i = 1; i <= m; ++i){
if(p[i]){
cout << p[i] << ' ' << i << '\n';
}
}
return 0;
}
時間複雜度 \(O(n \cdot (n + m))\)
空間複雜度 \(O(n + m)\)