模板总结——二分图最大匹配

基本概念

二分图:二分图指的是这样的一种图,其所有顶点可以分成两个集合X和Y,其中X或Y中任意两个在同一个集合中的点都不相连,所有边关联在两个顶点集中。

匹配:匹配是图边集的一个子集,满足任意两条边都不依附于同一个顶点

最大匹配:边数最多的匹配

饱和顶点:与匹配中的边相关联的顶点

M交错路:M是图的一个匹配,边在M和M的补集中交替出现的路叫M交错路

M增广路:起点和终点都是非饱和点的M交错路

算法原理

定理:一个匹配是最大匹配的充要条件是不存在增广路
匈牙利算法就是通过不断找增广路来增大匹配

几个重要结论

最小点覆盖:选最少的点使得每条边都至少和其中一个点关联。
最小点覆盖=最大匹配

最小边覆盖:选最少的边使得每个点都和所选边关联
最小边覆盖=顶点数-最大匹配

最小路径覆盖:用尽量少的不相交的简单路径覆盖有向无环图G的所有结点。
建立二分图G‘如下:
把所有顶点i拆成两个:X结点集中的i和Y结点集中的i’,如果有边i->j,则在二分图中连边i->j’。最小路径覆盖=G中的顶点数-G’的最大匹配.
如果题目可以用相交的简单路径去覆盖的话,需要用floyed算法去传递闭包,这样就有新的路径可以绕开交点,将模型转化成了用不相交的路径去覆盖了。比如poj2594

二分图最大独立集:在有N个点的图中选出m个点,使着m个点两两之间没有边,求m的最大值。
如果是二分图,那么最大独立集=N-最大匹配

模板

const int maxn=1600;
int from[maxn],vis[maxn];
int n;
vector<int> g[maxn];

bool Find(int u)
{
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(!vis[v])
        {
            vis[v]=1;
            if(from[v]==-1 || Find(from[v]))
            {
                from[v]=u;
                return true;
            }
        }
    }
    return false;
}
void solve()
{
    int ans=0;
    memset(from,-1,sizeof(from));
    for(int i=0;i<n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(Find(i)) ans++;
    }
    printf("%d\n",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值