题目连接
题目思路
如果不要去证明这个算法的正确性的话,我认为这只能算是一个简单贪心的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;
}