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

article/2025/9/17 10:05:40

一.概念部分

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)- 最大匹配数;


http://chatgpt.dhexx.cn/article/DBndjDNk.shtml

相关文章

二分图最大匹配及最大权匹配

二分图最大匹配学习 一.二分图的基本知识二.二分图最大匹配什么是二分图最大匹配怎么求二分图最大匹配 三.二分图最大权匹配四.例题训练三.最小点覆盖数 一位大佬的神级解释 本以为有了网络流&#xff0c;就不用再学匈牙利了&#xff0c;但在做题的过程中&#xff0c;发现有些…

二分图最大匹配问题(匈牙利算法)

什么是二分图 如果一个无向图的的顶点可以分为两个互不相交的子集A和B&#xff0c;那么它就是二分图。也就是说&#xff0c;A、B内部不存在连边&#xff0c;所有连边都一头连着A中的顶点&#xff0c;另一头连着B中的顶点。 什么是二分图最大匹配&#xff1f; 二分图最大匹配…

二分图 二分图最大匹配

首先来说一下什么是二分图。 二分图 二分图又称作二部图&#xff0c;是图论中的一种特殊模型。 设G(V, E)是一个无向图。如果顶点集V可分割为两个互不相交的子集X和Y&#xff0c;并且图中每条边连接的两个顶点一个在X中&#xff0c;另一个在Y中&#xff0c;则称图G为二分图。…

二分图最大匹配(最大流)

先举个例子&#xff0c;有N台计算机和K个任务&#xff0c;每个计算机只能执行一个任务&#xff0c;但可以执行多种任务。现在给出N和K&#xff0c;和其关系&#xff0c;求出最多能处理的任务数。 这就是典型的二分图&#xff0c;整张图被分为两半&#xff0c;一半是电脑&#…

图论总结(一)二分图最大匹配

二分图最大匹配 (一)、二分图 1、定义2、性质3、判定(二)、二分图的匹配 1、二分图的最大匹配2、 Knig定理及其证明3、最小边覆盖与最大独立集(三)、增广路径 1、定义2、性质3、寻找增广路(四)、匈牙利算法 1、找增广路经的算法2、实践3、算法分析(五)、例题 1、最小…

二分图的最大匹配

一、概念&#xff1a; 二分图&#xff1a;简单来说&#xff0c;如果图中点可以被分为两组&#xff0c;并且使得所有边都跨越组的边界&#xff0c;则这就是一个二分图。准确地说&#xff1a;把一个图的顶点划分为两个不相交集 U 和V &#xff0c;使得每一条边都分别连接U、V中的…

二分图最大匹配问题

最近在做的打车项目中&#xff0c;涉及到了用户叫单后&#xff0c;将所有出单司机和所有订单匹配的问题&#xff0c;借此来学习一下二分图的匹配算法。 一、无权二分图最大匹配 首先要区分一下各个概念&#xff1a; 匹配&#xff1a;图G的一个匹配是由一组没有公共端点的不是…

二分图最大匹配——匈牙利算法

二分图最大匹配 &#xff08;一&#xff09;、二分图的介绍1、定义2、充要条件 &#xff08;二&#xff09;、二分图的匹配1、二分图的最大匹配2、增广路径3、匈牙利算法&#xff08;1&#xff09;、复杂度&#xff08;2&#xff09;、算法思路&#xff08;3&#xff09;、代码…

B树最小高度和最大高度的推导

B树最小高度和最大高度的推导 对任意一棵包含n个关键字&#xff0c;高度为h&#xff0c;阶数为m的B树&#xff0c;其最小高度和最大高度的推导过程如下&#xff1a;

算法篇:树之树的高度

算法&#xff1a; 这一类题目很简单&#xff0c;不过却是树的最基本操作之一&#xff0c;引申为判断树是不是平衡二叉树。 一般做法是&#xff0c;计算二叉树的左右子树的高度1&#xff0c;然后取它们的最大值或者最小值。 题目1: https://leetcode-cn.com/problems/balanced-b…

【二叉树】最小高度树

0x00 题目 给定一个 有序 整数数组 元素各不相同且按 升序 排列 编写一个算法&#xff0c;创建一棵 高度最小 的二叉 搜索 树 给定有序数组: [-10,-3,0,5,9] 一个可能的答案是&#xff1a;[0,-3,9,-10,null,5] 它可以表示下面这个高度平衡二叉搜索树&#xff1a; 0 / \ -3 …

常见数据结构详细图解、树的高度、深度、层数、跳表、二叉搜索树、平衡二叉树、红黑树、B树、B+树

常见数据结构 常用的数据结构知识。 1.1 跳表 上图是一个有序链表&#xff0c;我们要检索一个数据就挨个遍历。如果想要再提升查询效率&#xff0c;可以变种为以下结构&#xff1a; 现在&#xff0c;我们要查询11&#xff0c;可以跳着来查询&#xff0c;从而加快查询速度。 …

树的高度 递归法和非递归法

递归法思路&#xff1a; 树的高度即节点子树的高度1&#xff08;节点子树的高度即左子树高度&#xff0c;右子树高度的最大值&#xff09; 代码如下&#xff1a; // Height_Recursive 递归法求树的高度 int Height_Recursive(TreeNode* pTree) {if (pTree NULL) {return 0;…

获取树高度的两种方法与完全二叉树的判断

树的高度 树的高度是节点高度的最大值。 每一层节点的高度如图所示。 方法一&#xff1a;递归 根节点的高度显然就是二叉树的高度。 /** * 获取树的高度* return*/ public int height(){return height2(root); }/*** 使用递归方法获取树的高度* param node* return*/ priv…

红黑树

一.简介 红黑树作为一种二叉搜索树的一种实现&#xff0c;红黑树的左右子树高度差可能大于 1。所以红黑树不是严格意义上的平衡二叉树&#xff08;AVL&#xff09;&#xff0c;但红黑树是黑色节点完美平衡&#xff0c; 其平均统计性能要强于 AVL 。 红黑树是每个节点都带有颜…

B树最大高度推导

文章目录 B树最大高度推导推导B树的最小高度推导最大高度 B树&#xff1a;MySQL数据库索引是如何实现的&#xff1f;1. 遇到问题2. 尝试用学过的数据结构解决这个问题3. 改造二叉查找树4. 索引的弊端 B树最大高度推导 【声明几个重要概念】 B树的关键字就是要查找的东西 B树…

红黑树详解

1&#xff0c;红黑树特点 每一个结点都有颜色&#xff0c;要么红色&#xff0c;要么黑色。根结点必须是黑色的。红色结点的子结点必须是黑色的。任何一个结点&#xff0c;到它所有叶子结点&#xff0c;经过相同个数的黑色结点。&#xff08;红黑树的平衡含义&#xff0c;左右高…

MYSQL的B+Tree索引树高度如何计算

我们使用MySQL数据库的时候&#xff0c;绝大部分的情况下在使用InnoDB存储引擎&#xff0c;偶尔会使用MyISAM存储引擎&#xff0c;至于其他存储引擎&#xff0c;我相信大家都很少接触到&#xff0c;甚至可能都没有听说过。所以本文只讲解InnoDB和MyISAM两个存储引擎的索引&…

红黑树高度上限的证明(通俗易懂)

先把结论放上&#xff0c;设红黑树的高度为h&#xff0c;总结点数为n&#xff0c;那么h与n的关系就是 下面开始证明过程 首先&#xff0c;从任意节点出发&#xff0c;到其子树的叶子节点的路径中黑色节点的数量称为该节点的黑高&#xff0c;即 bh 我们设根节点为T,那么根节点…

数据结构与算法(一): 树的高度和深度的区别

1.高度 对于高度的理解&#xff0c;我们不管他数据结构什么什么知识&#xff0c;就拿楼房来说&#xff0c;假如一个人提问&#xff1a;楼房的高度有好高&#xff1f;我们会下意识的从底层开始往上数&#xff0c;假如楼有6层&#xff0c;则我们会说&#xff0c;这个楼有6层楼那…