【模板】二分图匹配/一般图匹配——匈牙利算法/随机匈牙利算法

今天学习了匈牙利算法,顺便学习了一般图匹配的乱搞做法(被打死

模板题传送门:
http://uoj.ac/problem/78
http://uoj.ac/problem/79

二分图匹配的匈牙利算法

简要做法

匈牙利算法的主要思想是找增广路,和最大流算法类似。
每次对于一个点,找出一条交替路径,即匹配边、非匹配边交错,且开头结尾都是非匹配边的路径,并将这条路径上面的边取反(取->不取,不取->取),如果增广成功,则答案+1。

具体实现时,可以使用dfs来递归寻找增广路。

注意点

dfs过程中传入的顶点都是在图的一侧,同时vis数组要在每次增广之前清零,我因为这个WA了好几次...(菜不成声.jpg)

模板代码

//UOJ #78

#include 
using namespace std;
const int MAXN=505;
void rd(int &x){
    x=0; int ch=getchar();
    while(ch<'0'||'9'

一般图匹配的乱搞随机做法

正解

对于一般图上的最大匹配问题,由于奇数长度环的存在,不能直接套用匈牙利算法。

一个经典的解法是带花树,代码也十分简短、优美,读者可以参考网上的一些资料。

然而博主太弱了,只会随机乱搞。

具体做法

外层循环T次,对于每个点,内层循环T次,寻找增广路,在每次dfs开始时,对该点的出边进行随机打乱。

这个算法效率较高,正确率...实测也不低(如果出题人没有丧心病狂卡数据的话)。

细节

你可能需要一些精心选择的参数。

顺便写了一下手写随机函数rand()。

模板代码

//UOJ #79

#include 
using namespace std;
typedef unsigned long long ull;
const int MAXN=505, T=10, T2=10;
void rd(int &x){
    x=0; int ch=getchar();
    while(ch<'0'||'9'>16)&32767;
}
inline void shf(int *a, int n){
    if(!n) return;
    for(int t=0; tans) ans=tmp, memcpy(ma, m, sizeof(m));
    } return ans;
}
int main(){
    rd(N), rd(M);
    for(int i=0, u, v; i

转载于:https://www.cnblogs.com/will7101/p/6636025.html

你可能感兴趣的:(【模板】二分图匹配/一般图匹配——匈牙利算法/随机匈牙利算法)