图论——二分图

一、基本知识

/*二分图
 * 什么是二分图 : 可以将图中的点划分为两个集合 且集合内部没有边相连
 * 匹配: 一个匹配是一个边的集合 其中任意两条边都没有公共顶点。
 * 最大匹配 : 匹配边数最多的匹配
 * 交替路:从未匹配的点出发
 * 增广路:从未匹配的点出发,走交替路
 * 增广路性质: 长度是奇数
 * 匈牙利算法  二分图最大匹配
 * 带权二分图最大权完备匹配 KM
 */

二、匈牙利算法代码(转自https://blog.csdn.net/qq_40938077/article/details/80410356

#include<bits/stdc++.h>
#define MAXN 9999
using namespace std;
int nx,ny;//nx表示二分图左边顶点的个数,ny表示二分图右边顶点的个数
int m;//m代表边的条数
int cx[MAXN],cy[MAXN];//如果有cx[i]=j,则必有cy[j]=i,说明i点和j点能够匹配
int x,y;//x点到y点有边
int e[MAXN][MAXN];//邻接矩阵
int visited[MAXN];//标记数组,标记的永远是二分图右边的顶点
int ret;//最后结果
int point(int u)//这个函数的作用是寻找增广路和更新cx,xy数组,如果找到了增广路,函数返回1,找不到,函数返回0。
{
    for(int v=1;v<=ny;v++)//依次遍历右边的所有顶点
    {
        if(e[u][v]&&!visited[v])//条件一:左边的u顶点和右边的v顶点有连通边,条件二:右边的v顶点在没有被访问过,这两个条件必须同时满足
        {
            visited[v]=1;//将v顶点标记为访问过的
            if(cy[v]==-1||point(cy[v]))//条件一:右边的v顶点没有左边对应的匹配的点,条件二:以v顶点在左边的匹配点为起点能够找到一条增广路(如果能够到达条件二,说明v顶点在左边一定有对应的匹配点)。
            {
                cx[u]=v;//更新cx,cy数组
                cy[v]=u;
                return 1;
            }
        }
    }
    return 0;//如果程序到达了这里,说明对右边所有的顶点都访问完了,没有满足条件的。
}
int main()
{
    while (cin>>m>>nx>>ny)
    {
        memset(cx,-1,sizeof(cx));//初始化cx,cy数组的值为-1
        memset(cy,-1,sizeof(cy));
        memset(e,0,sizeof(e));//初始化邻接矩阵
        ret=0;
        while (m--)//输入边的信息和更新邻接矩阵
        {
            cin>>x>>y;
            e[x][y]=1;
        }
        for(int i=1;i<=nx;i++)//对二分图左边的所有顶点进行遍历
        {
            if(cx[i]==-1)//如果左边的i顶点还没有匹配的点,就对i顶点进行匹配
            {
                memset(visited,0,sizeof(visited));//每次进行point时,都要对visited数组进行初始化
                ret+=point(i);//point函数传入的参数永远是二分图左边的点
            }
        }
        cout<<ret<<endl;
    }
 
}
定理1(Konig 定理):最小点覆盖数 = 最大匹配数

点覆盖:点集合使得任意一条边至少有一个端点在集合中。

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

独立集:点集合中任何两个顶点都不互相连接。

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

路径覆盖:任何一个点都属于且仅属于一条路径。

/*
 *  最大匹配数   : 最大匹配的匹配边的数目
 *  最小点覆盖数 : 选取最少的点使得任意一条边至少有一个端点被选择
 *  最大独立数 :选取最多的点,使任意所选两点均不相连 = 顶点数 - 最大匹配数
 *  最小路径覆盖数 : 对于一个DAG 选择最少的路径使得每个顶点属于且仅属于一条路径,路长可为0
 *
 *  定理1 : 最大匹配数 = 最小点覆盖数 (Konig定理)
 *  定理2 : 最大匹配数 = 最大独立数
 *  定理3 : 最小路径覆盖数 = 顶点数 - 最大匹配数
 *	定理4 : 最大独立数 = 顶点数 - 最大匹配数
*/

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值