如果不要去证明这个算法的正确性的话,我认为这只能算是一个简单贪心的dfs
可能一直被它高深的名字骗了没有去深入学习
时间复杂度\(O(nm)\) \(n\)代表点数,\(m\)代表边数
算法流程大概是如下 参考洛谷的题解
1.从任意一个没有被配对的点x开始,从点x的边中任意选一条边。如果此时点i没有被配对那么配对成功,则找到了一条增广路。如果点i此时已经被配对了,那么可以尝试将点match[i]与其他点配对。如果尝试成功,则找到一条增广路。这里用match[ ]来记录配对关系, 即match[i] = x。 并且将配对数+1。 这个过程我们用dfs来实现。
2.如果配对失败,就从点x的边中重选一条边尝试。直到点x配对成功或尝试完x所有的边。
3.接下来对没有配对的点一一进行配对,直到所有的点都尝试完毕找不到新的增广路。
二分图染色好像能解决一堆覆盖问题,以后有机会再好好了解下吧
#include<bits/stdc++.h> #define fi first #define se second #define debug cout<<"I AM HERE"<<endl; using namespace std; typedef long long ll; const int maxn=5e2+5,inf=0x3f3f3f3f,mod=1e9+7; const double eps=1e-6; int n,m,e; vector<int> g[maxn]; bool vis[maxn]; int match[maxn]; bool dfs(int u){ for(auto x:g[u]){ if(vis[x]) continue; vis[x]=1; if(match[x]==-1||dfs(match[x])){ match[x]=u; return 1; } } return 0; } signed main(){ scanf("%d%d%d",&n,&m,&e); for(int i=1,u,v;i<=e;i++){ scanf("%d%d",&u,&v); g[u].push_back(v); } int ans=0; memset(match,-1,sizeof match); for(int i=1;i<=n;i++){ memset(vis,0,sizeof vis); ans+=dfs(i); } printf("%d\n",ans); return 0; }