匈牙利。
匈牙利算法,能在 的复杂度处理二分图最大匹配的问题,其中 是左部点个数, 是右部点个数, 是边数,马良极短,吊打网络流。
首先我们有很多关键点能想到这个,要么是涉及到匹配,或者是涉及到需要取出一些环的问题,这个是一个极好的处理方式。
算法流程就是一种调整法,考虑就是对于一个点,暴力去尝试匹配,如果不能匹配上它就失配了。暴力的过程则分为两种:
-
若该右部点没有匹配,直接匹配该右部点。
-
若该右部点有匹配,尝试让原来匹配的那个点找到新的匹配。
以下是简短的代码:
#include<bits/stdc++.h>
using namespace std;
const int M=1e3+5;
int mtch[M];
int visT[M];
int n,m,e,x,y;
vector<int> E[M];
int ans;
bool dfs(int now,int tg){
if(visT[now]==tg)return 0;
visT[now]=tg;
for(auto p:E[now])if(!mtch[p]||dfs(mtch[p],tg)){
mtch[p]=now;
return 1;
}
return 0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m>>e;
for(int i=1;i<=e;i++)cin>>x>>y,E[x].push_back(y);
for(int i=1;i<=n;i++)ans+=dfs(i,i);
cout<<ans;
return 0;
}
其中 dfs
函数就是尝试匹配的最主要过程。递归的过程就是找新匹配的过程。为什么可以用 vis
数组?因为再次访问到只有两种情况,要么是再次尝试替换这个点,要么是替换成环,如果我们找到匹配就退出,那么这两种情况一定无解。
例题:CF387D George and Interesting Graph
George 喜欢图,因此它想让图更有趣。他认为有趣的图满足以下条件:
- 没有重边;
- 存在结点 (称为中心),使得对于图中的任意结点 ,都有边 和 ,注意自环 也应该存在;
- 除去中心外,每个点的入度和出度都恰好为 ;
显然很少有图有趣,但 George 可以把图变得有趣:每次他可以增加一条边或者删除一条已经存在的边。
现在给出图 ,George 想知道他最少做多少次操作可以使它变得有趣。
。
枚举中心,剩下就变成尝试连出一些简单环使得一个点在且仅在一个简单环里,这个直接上二分图匹配就能求出最多有多少条已有边在这个系统里。
本文作者:xingyu_xuan
本文链接:https://www.cnblogs.com/xingyuxuan/p/18457157
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步