二分图匹配

二分图匹配

匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。

无权图

匈牙利算法

#include<bits/stdc++.h>
using namespace std;
const int MAX = 10000;
vector<int> G[MAX];
int vis[MAX];
int link[MAX];//代表当前状态Y中与X相连的点(即d[y] = x)
int n, m;//n为X集合点数,m为Y集合点数(这里默认点的序号为X到Y依次递增)
 
int find(int t)//这一个t保证它是X中的点
{
    for(int i = 0; i < G[t].size(); i++){//从Y中的每一点开始找
        int tmp = G[t][i];//与t相连的tmp
        if(!vis[tmp]){//如果这点没有被前面几次找过,
            vis[tmp] = 1;
            if(link[tmp] == -1 || find(link[tmp])){//这里寻找增广路径的结束条件就是找到Y中未被配对过的点,如果这点被配对过,那么就从这点配对的X中的点进行新一轮的can()
            //第一个条件表明Y中的tmp还未和X中的某个点匹配起来,第二个条件理解为link[tmp]中存的之前X中的点是否还能找到其他可以匹配的点
               link[tmp] = t;
               return 1;
            }
        }
    }
    return 0;
}
 
int maxmatch()
{
    int num = 0;
    for(int i = 1; i <= n; i++){
        memset(vis, 0, sizeof(vis));
        if(can(i)){
            num++;
        }
    }
    return num;
}
 
int main()
{
    while(scanf("%d %d", &n, &m) != EOF){
        for(int i = 1; i <= n; i++)
            G[i].clear();
        memset(link, -1, sizeof(link));
        int s;
        scanf("%d", &s);
        while(s--){
            int a, b;//表示X中的a与Y中的b相连
            scanf("%d %d", &a, &b);//假设输入的点X和Y分开输入(都是从1开始)
            G[a].push_back(b+n);
            G[b+n].push_back(a);//由于是无向图
        }
        printf("%d\n", maxmatch());
    }
    return 0;
}

最小覆盖

二分图的最小覆盖分为最小顶点覆盖和最小路径覆盖:

①最小顶点覆盖是指最少的顶点数使得二分图G中的每条边都至少与其中一个点相关联,二分图的最小顶点覆盖数=二分图的最大匹配数;

②最小边覆盖,是指用尽量少的不相交简单路径覆盖二分图中的所有顶点。二分图的最小路径覆盖数=|V|-二分图的最大匹配数;

最大独立集

最大独立集是指寻找一个点集,使得其中任意两点在图中无对应边。对于一般图来说,最大独立集是一个NP完全问题,对于二分图来说最大独立集=|V|-二分图的最大匹配数

最小路径覆盖(DAG)

描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值