在HDU 2063 过山车中,我们遇到的是二分图最大匹配问题。那么什么是二分图最大匹配呢?我找了很多资料,发现下面的博主写的很详细,在此贴上文章链接。
https://blog.csdn.net/qq_38956769/article/details/80238896
请务必先看懂文章再来做这道题。
下面是我看懂后写下的AC代码:
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 1010;
vector<int> adj[maxn]; //邻接表
int k, m, n, ans; //k是边数、m是女生数、n是男生数、ans是最大匹配数
void addEdge(int u, int v){
adj[u].push_back(v);
adj[v].push_back(u);
}
//读入数据,建图
void init(){
scanf("%d%d", &m, &n); //输入女生人数、男生人数
for(int i = 1; i <= m + n; i++){
adj[i].clear();
}
for(int i = 1; i <= k; i++){
int u, v;
scanf("%d%d", &u, &v);
v += m; //男生编号设为 m+1 ~ m+n
addEdge(u, v); //添加边
}
}
//深搜,找增广路径
bool vis[maxn]; //是否已访问
int match[maxn]; //匹配顶点号,match[u] = v表示u的顶点已匹配了顶点v
bool DFS(int u){
for(int i = 0; i < adj[u].size(); i++){
int v = adj[u][i];
if(vis[v] == true) //若已访问
continue;
vis[v] = true;
//若Y部的顶点v并没有匹配点 或 其匹配好的顶点能找到其他顶点匹配
if(!match[v] || DFS(match[v])){
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
//匈牙利算法主函数
void solve(){
ans = 0;
memset(match, 0, sizeof(match));
//枚举左半边(女生)的每个点
for(int i = 1; i <= m; i++){
memset(vis, false, sizeof(vis));
if(!match[i]){
if(DFS(i))
ans++;
}
}
}
int main(){
while(scanf("%d", &k) && k){ //输入0结束
init();
solve();
printf("%d\n", ans);
}
return 0;
}