二分图---匈牙利算法

今天集训,想起来之前看的一脸懵逼的二分图,打算再捡起来看一次,然后翻到了这个用海贼王解释匈牙利算法的二分图算法,瞬间开朗,但貌似里面有点地方的代码还是不清楚的,下面代码会写得相对详细一点
顺带去做了几道二分图的基础题HDU–2063(由于今天好像HDU挂了,只过了一题)POJ–1274,POJ–2239,POJ–2536

这些题都很水,开头数据处理下直接套匈牙利的版就行了
二分图就不讲了,以下是百度百科的解释
二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
总而言之,就是只能分为两个帮派的图,出现第三个帮派的都不叫二分图


然后二分图有几个基本的概念:

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

最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择

最大独立数:选取最多的点,使任意所选两点均不相连

最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。

定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)

定理2: 最大独立数 = 顶点数 - 最大匹配数

定理3:最小路径覆盖数 = 顶点数 - 最大匹配数


最后附上匈牙利模板,要理解的话请点击上面那个连接=-=这里就不详解了

int map[maxn][maxn];  //记录两者是否有关系 
int used[maxn];       //记录是否有用过 
int upon[maxn];       //记录他所匹配的人 


//下面定义A集合中的某个值为ai,B集合的某个值为bi
bool dfs(int master,int m){                        //传入ai和B集合中单个子集的总数
    for(int i = 1;i <= m;i++){                     //遍历B集合的所有单个子集
        if(map[master][i] && !used[i]){            //如果ai和bi有关且bi没有被访问过
            used[i] = 1;                           //标记成访问的
            if(upon[i] == -1 || dfs(upon[i],m)){   //如果bi没有被标记成某个ai用过的,或者找找bi相应的ai一直递归下去看看有没有某个bi能换一个ai
                upon[i] = master;                  //记录bi相对应的ai
                return true;                       //找到对象,返回成功
            }
        }
    }
    return false;                                  //找不到对象,返回失败
}

int huangary(int n,int m){
    int res = 0;
    memset(upon,-1,sizeof(upon));
    for(int i = 1;i <= n;i++){       //匹配所有解
        memset(used,0,sizeof(used));
        if(dfs(i,m))
            res++;
    }
    return res;                      //返回最终解
}

今天集训最后一天,又撸懂了一个算法=-=

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值