二分图与网络流

一、二分图

1、二分图匹配(匈牙利算法)

匈牙利算法的本质是在二分图里面搜索增广路,因为每条增广路取反可以使最大匹配+1。

可以证明:如果在某一时刻,找不到以x为起点的增广路,则增广几轮之后仍不会找到。
所以只需要遍历一次左部的点,对于每个点寻找一次增广路即可。

需要注意的是vis[i]的功能,因为增广路为 u − > t o − > u ′ − > t o ′ . . . u->to->u'->to'... u>to>u>to...因为我们知道增广路没有环,所以需要标记 v i s [ t o ] vis[to] vis[to]避免环的产生。

bool dfs(int x)
{
    
    
    for(auto to:v[x])if(vis[to]==0)
    {
    
    
        vis[to]=1;
        if(belong[to]==0)
        {
    
    
            belong[to]=x;
            return true;
        }
        else if(dfs(belong[to]))
        {
    
    
            belong[to]=x;
            return true;
        }
    }
    return false;
}
rep(i,1,n)
{
    
    
    memset(vis,0,sizeof(vis));
    if(dfs(i))tot++;
}

例1.1.1 P3386 【模板】二分图最大匹配
例1.1.2 P2055 [ZJOI2009]假期的宿舍
例1.1.3 P2756 飞行员配对方案问题

2、二分图最大匹配(KM算法)

二分图最大匹配是在完全匹配的基础上求边权和的最大值。
贪心的看,如果每个左部点能匹配到他的最大边,这个时候得到的匹配就是最大匹配。

所以我们给每个左部点一个上标(初始值为它所有连边边权的最大值),表示这个点可匹配的边权。容易知道如果此时匹配成功即为最大匹配,但是这样可能无法完全匹配。

所以我们需要修改一下左部点的上标,使得上标和减少的最小,且能找到匹配,容易知道这个时候是最大匹配。KM算法的本质就是实现这种修改。

容易知道,和匈牙利算法一样,点匹配的顺序并不影响最终的答案,所以我们只需要按顺序加入点,对于每个点,修改上标至能使该点匹配,这样的贪心修改是可以得到全局最优解的。

KM算法(理解篇)
KM算法(运用篇)
【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))

例1.2.1 P6577 【模板】二分图最大权完美匹配
一道非常卡的例题,得用bfs才能过,我用邻接表存图也过不了。

遗留问题1:为什么dfs的km算法在上述例题里会TLE
遗留问题2:为什么bfs+邻接表的km算法在上述例题里会TLE
遗留问题3:为什么非交错边的松弛数组slake值要减去delta

例1.2.2 HDU-2853 Assignment

总体上就是km算法匹配求最优匹配。但是加入了一点点操作,使得匹配的时候优先匹配已经分配的任务。
我们将原来的权值扩大k倍,让它是k的倍数。而那些已经分配的任务,我们+1。这样做的操作是方便计数的同时让km优先匹配这个任务(因为km算法是类似贪心算法,优先匹配权值大的,而+1,由于比它大的数至少大k倍,所以不会改变匹配结果,等于它的是由于它+1,就优先匹配它了)那么对于统计不变的个数就是:ans%k,统计多少个1。变的个数就是:n-ans%k。而对于匹配总权值:除k,取整就行。

猜你喜欢

转载自blog.csdn.net/solemntee/article/details/114388900
今日推荐