二分图
每条边的两个结点都分别在X点集,和Y点集中。
匹配
集合M中存的每一条边的端点都不会重复
最大匹配:使集合大小最大(可能有多个最大匹配)
增广路径
在匹配M中的一条交错路径,它的两个端点都不与M中的边关联
ps.交错指一条不属于M的边+属于M的边+不属于M的边...
出现一条新的增广路径则匹配成功的边数+1,因为交错的边反转(属于<->不属于)。
匈牙利算法(hungry算法)
用途:求二分图的最大匹配
流程:
用link表示Y集合中的点当前配对的X集合中的点
(假设点属于X,Y集合)
用每个X集合中的点去配Y集合中的点,若不改变前面匹配出的最大边数出现新的增广路径,最大边数+1
下面这份代码的核心:
能否找到两个端点是都没被匹配过的,能,就在回溯的时候就将增光路的匹配情况取反
代码:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int nxt[N],link[N],to[N],head[N],num;
bool road[N];
void add_edge(int u,int v) {
num++; nxt[num]=head[u]; to[num]=v; head[u]=num;
}
bool Find(int u) {
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(!road[v]) {
road[v]=true;
if(!link[v]||Find(link[v])) { //若v原来已经属于link[v]了那,试图让link[v]去连别的边,如果成功(Find(link[v])==true)那就更新link[v].
link[v]=u;
return true;
}
}
}
return false;
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
int c,v;
scanf("%d",&c);
for(int j=1;j<=c;j++) {
scanf("%d",&v);
add_edge(i,v);
}
}
int tot=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) road[j]=false;
if(Find(i)) tot++;
}
printf("%d",tot);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人