二分图最大匹配与最大独立集

2023-10-26

一.概念部分

1.什么是二分图?

通俗的说法:就是可以把图分成两部分,每一部分任意两点之间没有关系(同一部落),两部分之间点可能存在多种关系。

2.怎么判断二分图?

(1)理论判定:如果某个图为二分图,那么它至少有两个顶点,且其所有回路的长度均为偶数,任何无回路的的图均是二分图。

如图:

                                                              

    二分图                                                                                                  非二分图

(2)代码判断:利用染色法,用两种颜色对图染色,若能全部染色没有冲突则为二分图

代码:

3.二分图最大匹配问题:

现在有了二分图,我们来想,假如两部分ab之间的边表示A部分的a可以和B部分的b进行配对,并且每个人只能匹配一个人,那么怎么能在不产生冲突的条件下,匹配最多的对数呢?

二.算法部分

1.匈牙利算法解决二分图最大匹配问题

(1):https://blog.csdn.net/dark_scope/article/details/8880547

(2)实质:先到先得,能让就让;  寻找增广路;

(3)增广路径的性质:

有奇数条边。

起点在二分图的左半边,终点在右半边。

 路径上的点一定是一个在左半边,一个在右半边,交替出现。(其实二分图的性质就决定了这一点,因为二分图同一边的点之间没有边相连,不要忘记哦。)

整条路径上没有重复的点。

起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。

路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。

最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。

(4)复杂度:O(m*n)

(5)代码:HDU 2063

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000 + 7;
bool used[maxn];
int Maching[maxn],k,n,m,tot,head[maxn];
struct Edge{
   int to,next;
}edge[maxn*2];
void addEdge(int a,int b){
    edge[tot].to = b;edge[tot].next = head[a];head[a] = tot++;
}
void init(){
    tot = 0;
    memset(head,-1,sizeof(head));
    memset(Maching,-1,sizeof(Maching));
}
bool DFS(int p){
   for(int i = head[p];~i;i = edge[i].next){
       int to = edge[i].to;
       if(!used[to]){//每试图让过
            used[to] = 1;//让一次
            if(Maching[to]==-1||DFS(Maching[to])){//没配对过/配对了但是可以让出来
                Maching[p] = to;Maching[to] = p;//配对成功
                return true;
            }
       }
   }
   return false;
}
int Hungary(int len){
   int sum = 0;
   for(int i = 1;i<=len;i++){//试图配对每一个左部分点
       memset(used,0,sizeof(used));
       if(DFS(i))sum++;//配对成功
   }
   return sum;
}
int main()
{
    while(scanf("%d",&k)!=EOF&&k){
        init();
        scanf("%d%d",&m,&n);
        for(int i = 0;i<k;i++){//k对
            int a,b;
            scanf("%d%d",&a,&b);//左部分 ---  右部分
            addEdge(a,m+b);//加边
        }
        int ans = Hungary(m);
        printf("%d\n",ans);
    }

    return 0;
}

 

2.匈牙利的优化算法----Hopcroft-Karp(HK)算法

参考:https://blog.csdn.net/qq_39792342/article/details/82017123

(1)思想:在匈牙利中,我们每次匹配一个点,寻找一条增广路,很浪费。我们可以在一次匹配中利用BFS尝试寻找多条增广路,然后在寻找配对时,当dist[p] ==dist[x] + 1时,p才是x的下一个增广节点。

(2)做法:BFS找增广路 + DFS进行匹配

(3)代码:HDU - 2389 

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 4000 + 7;
struct Node{
   int x,y,speed;
}node[maxn*2];
int n,m,dist[maxn*2],Maching[maxn*2];
vector<int>G[maxn];
int Length(int p,int q){
   return  (node[p].x - node[q].x)*(node[p].x - node[q].x) + (node[p].y - node[q].y)*(node[p].y - node[q].y);
}
bool BFS(){//寻找增广路
   memset(dist,-1,sizeof(dist));
   queue<int> que;
   for(int i = 1;i<=m;i++){
       if(Maching[i]==-1){que.push(i);dist[i] = 0;}
   }
   bool flag = false;
   while(!que.empty()){
       int p = que.front();
       que.pop();
       int len = G[p].size();
       for(int i = 0;i<len;i++){
           int to = G[p][i];
           if(dist[to]==-1){
               dist[to] = dist[p] + 1;
               if(Maching[to]==-1)flag = true;
               else {dist[Maching[to]] = dist[to] + 1;que.push(Maching[to]);}
           }
       }
   }
   return flag;
}
bool DFS(int p){//搜索匹配
   int len = G[p].size();
   for(int i = 0;i<len;i++){
       int to = G[p][i];
       if(dist[to]==dist[p] + 1){
           dist[to] = -1;
           if(Maching[to]==-1||DFS(Maching[to])){
               Maching[to] = p;
               Maching[p] = to;
               return true;
           }
       }
   }
   return false;
}
inline int HK(){
   int cnt = 0;
   while(BFS()){
      for(int i = 1;i<=m;i++){
          if(Maching[i]==-1&&DFS(i))cnt++;
      }
   }
   return cnt;
}
int main()
{
    int T;
    scanf("%d",&T);
    int kase = 0;
    while(T--){
        int t;
        memset(Maching,-1,sizeof(Maching));
        scanf("%d",&t);
        scanf("%d",&m);
        for(int i = 1;i<=m;i++){
            G[i].clear();
            scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].speed);
        }
        scanf("%d",&n);
        for(int j = m+1;j<=m+n;j++){
            scanf("%d%d",&node[j].x,&node[j].y);
            for(int k = 1;k<=m;k++){
                int time = Length(k,j);
                if(time<=node[k].speed*node[k].speed*t*t)G[k].push_back(j);
            }
        }
        int ans = HK();
        printf("Scenario #%d:\n%d\n\n",++kase,ans);
    }
    return 0;
}

 

三.拓展部分:

1.二分图完美匹配:如果左侧部分的所有点都能够匹配,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。但并非每个图都存在完美匹配。且 最大匹配不一定是完美匹配。

解决:求最大匹配,若最大匹配数==所有点数则为完美匹配

 

2.二分图的最小点覆盖:最小顶点覆盖:实质是个点集,点集里面的点能覆盖所有的边,最小顶点覆盖就是满足这个要求的点集中点数最小的那个。

解决:二分图的最小点覆盖 = 二分图最大匹配数

 

3.二分图最大独立集:实质是个点集,这个集合里的点无论怎样都两两相连不到一起,满足这个要求的点数最多的一个。也就是集合里任意两点之间无关系。

解决:二分图最大独立集 = 节点数(n)- 最大匹配数;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二分图最大匹配与最大独立集 的相关文章

  • [USACO06FEB]Steady Cow Assignment G【二分+最大流】

    题目链接 P2857 USACO06FEB Steady Cow Assignment G 有N头牛 B个牛棚 告诉你每头牛心里牛棚的座次 即哪个牛棚他最喜欢 哪个第2喜欢 哪个第3喜欢 等等 但牛棚容量一定 所以每头牛分配到的牛棚在该牛心
  • AcWing 1055. 股票买卖 II

    输入样例1 6 7 1 5 3 6 4 输出样例1 7 输入样例2 5 1 2 3 4 5 输出样例2 4 输入样例3 5 7 6 4 3 1 输出样例3 0 样例解释 样例1 在第 2 天 股票价格 1 的时候买入 在第 3 天 股票价格
  • LeetCode-Python-1584. 连接所有点的最小费用(MST)

    给你一个points 数组 表示 2D 平面上的一些点 其中 points i xi yi 连接点 xi yi 和点 xj yj 的费用为它们之间的 曼哈顿距离 xi xj yi yj 其中 val 表示 val 的绝对值 请你返回将所有点
  • 图论:Dijkstra算法——最详细的分析,图文并茂,一次看懂!

    文章目录 1 Dijkstra算法简介 2 算法实现范例 3 邻接矩阵 4 Dijkstra 算法的 C 描述 5 Dijkstra 算法的 Matlab 描述 6 温故知新 1 Dijkstra算法简介 背景 迪杰斯特拉算法 Dijkst
  • 图论感想

    图论基础无非也就是图存储 遍历 有向图无向图的连通性 分为图联通和联通分量 有向图为强联通分量 割点与割边 本人目前还没有看网络流内容 只是大致知道是什么 觉得也是图论一部分 个人认为学东西应该大体了解一下所学内容 每学一个必要好好思考 最
  • 无向图的遍历-BFS与DFS

    一 理论部分 无向图的遍历可用深度搜索 DFS 与广度搜索 BFS 深度搜索的基本方式是由图的一个节点1出发然后随机选一个与其相邻的节点2 接着在选择一个与其相邻的节点3 当一条路遍历完后再选择最近一个遍历过的 且相邻节点有未遍历过的节点
  • 2021级新生个人训练赛第38场

    问题 A chicken 题目描述 小 x 非常喜欢小鸡翅 他得知 NSC 超市为了吸引顾客 举行了如下的活动 一旦有顾客在其他超市找到更便宜的小鸡翅 NSC 超市将免费送给顾客 1000g 小鸡翅 小 x 为了尽可能的省钱 走遍了各大超市
  • 树形dp(例题)

    树的最长路径带权值 树的直径可能时红色的边 从上图可以看出 每次要两个变量存放以u为根 最长路径d1 和次长路径d2 那么整个树的最长路径就有可能是d1 d2 我们每次要返回以u为根的贯穿试的最长路径 给他的父节点判断使用如下图 inclu
  • 【DFS和BFS习题集+分类总结】(更新至2023.1.1)(17788字)

    目录 第一题 八皇后 dfs 路径输出 前驱版 第一题的补充练习 N皇后 dfs 打表 第二题 自然数的拆分 第三题 图的遍历 BFS和DFS 第四题 fire net dfs 第五题 nightmare 可以走回头路的DFS 第六题 滑雪
  • 矩阵树定理

    启蒙 http zhengruioi com contest 1416 T1 T2的10分暴力 后面是论文科技 不搞了 https www luogu com cn problem P6178 O n 3
  • AcWing 378. 骑士放置(最大独立集&&匈牙利算法)

    输入样例 2 3 0 输出样例 4 解析 题意为求最大独立集 即为总点数 最小点覆盖 include
  • POJ 3259 Wormholes(最短路——Bellman-ford)

    A Wormholes While exploring his many farms Farmer John has discovered a number of amazing wormholes A wormhole is very p
  • Summer Holiday HDU - 1827 强连通分量+缩点

    To see a World in a Grain of Sand And a Heaven in a Wild Flower Hold Infinity in the palm of your hand And Eternity in a
  • 数据结构算法—邻接表存储的无向图求连通分量个数

    数据结构算法 邻接表存储的无向图求连通分量个数 邻接表存储结构 typedef struct ArcNode int adjvex 边指向的顶点 struct ArcNode nextarc 下一条边的指针 ArcNode typedef
  • 1600*B. pSort(并查集)

    解析 并查集 将能够交换的位置相连 查看对应的位置能够交换 include
  • 图 - Java实现无向带权图的邻接矩阵表示法

    图 Java实现无向带权图的邻接矩阵表示法 1 图 1 1 图的介绍 图 Graph 是一种复杂的非线性表结构 图中的元素我们就叫做顶点 vertex 图中的一个顶点可以与任意其他顶点建立连接关系 我们把这种建立的关系叫做边 edge 跟顶
  • 第14届蓝桥杯C++B组省赛

    文章目录 A 日期统计 B 01 串的熵 C 冶炼金属 D 飞机降落 E 接龙数列 F 岛屿个数 G 子串简写 H 整数删除 I 景区导游 J 砍树 今年比去年难好多 Update 2023 4 10 反转了 炼金二分没写错 可以AC了 U
  • 数模培训第二周——图论模型

    图论中最短路算法与程序实现 图论中的最短路问题 包括无向图和有向图 是一个基本且常见的问题 主要的算法有Dijkstra算法和Floyd算法 Floyd算法 简介 Floyd Warshall算法 英语 Floyd Warshall alg
  • D (1173) : A DS二叉树_合并二叉树

    文章目录 一 题目描述 二 输入与输出 1 输入 2 输出 三 参考代码 一 题目描述 给定两个二叉树 输出这两个二叉树合并后形成的二叉树 依次输出前序遍历 中序遍历 后序遍历 二 输入与输出 1 输入 第一行输入t 表示有t个测试样例 第
  • 860.染色法判定二分图

    二分图是指一个图中的所有顶点可以分为两部分 并且每条边连接的是属于不同部分的两个顶点 include

随机推荐

  • Shell脚本入门

    Shell脚本入门 1 基本概念 Shell是一门弱类型 解释型 非编译型语言 Shell中无数据类型 Shell的作用是解释执行用户的命令 Shell执行命令的方式有两种 1 交互式 用户输入一条命令 shell就解释执行一条 2 批处理
  • 名为dash的蓝色插嘴小机器人_全球最出色的十大教育机器人

    2016年 阿尔法狗战胜围棋世界冠军李世石 成为人工智能发展的标志性事件 万物互联的时代 人工智能正掀起一场影响深刻的技术革命 谷歌 苹果 BAT 华为巨头们纷纷布局人工智能 有人猜测 互联网 过后 我们可能会迎来机器人 听到这个消息 爸爸
  • [PCIe] SR-IOV (单根虚拟化) 及linux驱动浅析(device的PF和VF及其驱动)

    网上从服务器和虚拟化层面介绍SR IOV应用的文章很多了 本文重点从支持SR IOV的设备 EP 及其驱动来讨论 对于SR IOV的设备 EP 来说 无非就是一个device通过物理功能 PF 虚拟出关联的若干个虚拟功能 VF host的驱
  • 某公司的雇员分为以下若干类: Employee:这是所有员工总的父类, 属性: 员工的姓名,员工的生日月份。 方法:getSalary(

    代码 某公司的雇员分为以下若干类 Employee 这是所有员工总的父类 属性 员工的姓名 员工的生日月份 方法 getSalary intmonth 根据参数月份来确定工资 如果该月员工过生日 则公司会额外奖励100 元 Salaried
  • 在proteus中继电器的驱动与使用

    在进行proteus仿真驱动继电器时候 因为第一次接触和学习继电器遇到了无论采用电源驱动还是三极管放大驱动都无法驱动的问题 所以就查了继电器的资料和proteus中的默认设置 发现原来是proteus中继电器默认驱动电压为12V 所以我们需
  • CF 709C

    感谢这个题让我进了前1000 思路 特殊条件切入 一开始想跑网络流 但边数 点数太多 所以就需要找此题和常规网络流的区别 看到 M 2 gt 尽可能使用M 2这个条件构造解 gt 少于M 2的全选 gt 剩下的全是大于M 2的 gt 如果每
  • linux-docker

    unix liunx windows linux 文件系统 所有的资源都是目录在 root 根目录下 一 指令 ip addr ifconfig cd ls vim sudo 管理员身份 代表换行输入 pwd 查看所在目录 sudo sys
  • 12306模拟登陆一直提示系统繁忙_12306买高铁火车票显示待核验怎么办,最新解决方案...

    知道有些人没耐心 先说解决核心是12306里面人脸识别 亲测有效 全文没几个字一定要看不用去车站走冤枉路啊 身份信息不能自动核验 相信吃过亏的不止我一个 网上找了很多方法不行 问客服也没用 终于自己找到一个方法 相继解决了我妈和我朋友的待核
  • Maven项目中properties文件的加载方式

    Maven项目中 读取properties配置文件 1 properties文件在src main java的根目录中时加载文件使用 PropertyConfigurator configure log4j properties 2 pro
  • FFmpeg进阶: 音频滤镜大全

    在做音频处理模块的时候 为了对声音进行优化处理 我很多时候会使用各种算法对音频进行变换 效果包括变音变调 声音降噪等等 其实FFmpeg库里的滤镜模块包含了很多有用的音频滤镜算法 这对于提升开发效率避免重复造轮子是很有帮助的 这里翻译了一下
  • Android apk 项目一键打包并上传到蒲公英

    项目一键打包并上传到蒲公英 缘由 测试流程由 打包 找包准备上传 填写更新信息 然后上传 过于复杂 所以想要简化开发 阅读须知 需要读者了解如何在项目里面建立一个空的gradle plugin的过程 否则这篇文章不适合你 开始分析 我想要的
  • jdbc控制自动提交功能

    import java sql Connection import java sql DriverManager import java sql ResultSet import java sql SQLException import j
  • opencv-python入门学习(1)

    opencv python入门 环境安装与配置 图像入门 图片的读取 显示和保存 cv imread 读取图像 cv imshow 显示图像 cv imwrite 储存图像 视频的读取 显示和保存 从摄像机 文件中读取并显示视频 保存编辑后
  • npm安装composer-rest-server等出现错误node-pre-gyp install --fallback-to-build --library

    npm安装composer rest server等出现错误node pre gyp install fallback to build library grpc 1 10 1 install usr local lib node modu
  • 20大中国式弱点营销

    什么是弱点营销 宇宙的精灵 万物的灵长 说的是人类 但现实中 人性的弱点也不少 贪婪 恐惧 嫉妒 懒惰 好色 贪慕虚荣 难抵诱惑 害怕孤独 热爱免费 重视等级 迷信专家 崇拜名人 喜随波逐流 关于人性的一切弱点 正在被消费社会利用和营销 一
  • vector中find 的用法

    vector没有自带的find函数 需要用普通的find函数 使用如下 vector
  • CH2-Java编程基础(7个案例实现)

    案例2 1 库房出入货物程序设计 案例介绍 任务描述 现要对华为和小米两种手机产品进行入库 本案例要求编写一个模拟商品入库的程序 可以在控制台输入入库商品的数量 最后打印出仓库中所有商品详细信息以及所有商品的总库存数和库存商品总金额 商品信
  • 斗地主发牌算法JAVA

    首先定义一个卡牌类 public class Card private String numb private String color private int index public Card public Card String nu
  • 【vue】使用了 keep-alive 的 include,但是切换 router-view,页面还是会刷新

  • 二分图最大匹配与最大独立集

    一 概念部分 1 什么是二分图 通俗的说法 就是可以把图分成两部分 每一部分任意两点之间没有关系 同一部落 两部分之间点可能存在多种关系 2 怎么判断二分图 1 理论判定 如果某个图为二分图 那么它至少有两个顶点 且其所有回路的长度均为偶数