图论-二分图匹配匈牙利算法
不得不说,如果以现实角度代入此算法的理解,就合理了很多,虽然有悖道德准则
重点在于以下几点
- 每次给女生分配男生前,都把男生全部初始化为可预定状态(即使他已经被别人成功匹配了)
- 在所有女生中意的男生中遍历,如果发现该男生可预订就先预定,然后看他是否已经有主了,如果有主了,就
dfs(match[i]),(跟当前那个匹配这个男生的女生商量能不能换,此时 dfs 进去,该男生预定状态是还在的,所以不会出岔子),当然这一步正经来说叫寻找增广路
然后是代码:
点击查看代码
int n, m;
int match[N], reserve[N];
int G[510][510];
bool dfs(int u){
// u For Girl, i For Boy;
for(int i = 1; i <= m; i++){
if(!reserve[i] && G[u][i]){
reserve[i] = 1;
if(!match[i] || dfs(match[i])){
match[i] = u;
return true;
}
}
}
return false;
}
由于匈牙利算法是O(nm)的,所以直接用邻接矩阵存图就好了
2024.6.7 不,还是用链式前向星再写一份
int n, m;
int head[N], cnt;
struct Edge{
int from, to, nxt;
}e[N << 1];
void add(int u, int v){
e[++cnt].from = u;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int match[N], reserve[N];
bool dfs(int u){
// u For Girl, i For Boy;
for(int i = head[u]; i != 0; i = e[i].nxt){
int v = e[i].to;
if(!reserve[v]){
reserve[v] = 1;
if(!match[v] || dfs(match[v])){
match[v] = u;
return true;
}
}
}
return false;
}
void solve() {
int cnte;
cin >> n >> m >> cnte;
for(int i = 1; i <= cnte; i++){
int u, v;
cin >> u >> v;
add(u, v);
}
int ans = 0;
for(int i = 1; i <= n; i++){
memset(reserve, 0, sizeof(reserve));
if(dfs(i)) ans++;
}
cout << ans << endl;
}

浙公网安备 33010602011771号