首页 > 其他分享 >无权二分图的最大匹配

无权二分图的最大匹配

时间:2024-07-18 13:31:28浏览次数:7  
标签:二分 无权 匹配 增广 int vector path

原作者:https://blog.csdn.net/KYJL888/article/details/106055942

1.二分图的基本知识点

二分图:简单来说图中的点可以被分为两组,并且使得所有边都跨越组的边界,这就是一个二分图。准确来说:把一个图的顶点划分为两个不相交集U和V,使得每一条边都分别连接U和V中的顶点。如果存在这样的划分,则此图为一个二分图。
图1是一个二分图,为了清晰我们都画成图2的形式。

匹配:$\color{blue} {在图论中,一个【匹配】是一个边都集合,其中任意两条边都没有公共顶点。} $例如,图3、图4中红色的边就是图2的匹配。

我们定义匹配点、匹配边、未匹配点、未匹配边,它们的含义非常显然。例如图3中1 4 5 7为匹配点,其他为未匹配点;1-5、4-7为匹配边,其他为非匹配边。

最大匹配:一个图中所有的匹配中,所含\(\color{green} {匹配边数最多的匹配,}\)称为这个图的最大匹配。图4是一个最大匹配,它包含4条匹配边。

求解最大匹配问题的一个算法是匈牙利算法,下面的概念都为这个算法服务。

交替路:从一个未匹配点出发(右),依次经过非匹配边、匹配边、非匹配边....形成的路径叫做交替路。

增广路:从一个未匹配点出发(右),走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路(agumenting path)。例如,图5中的一条增广路如图6所示(图中的匹配点均用红色标出):

增广路有一个重要特点:非匹配边比匹配边多一条。因此研究增广路的意义是改进匹配。只要把增广路中的匹配边和非匹配边的\(\color{green} {身份交换}\)即可。由于中间的匹配节点不存在与其他相连的匹配边,所以这样做不会破坏匹配的性质。交换后,图中的匹配边数目比原来多了1条。

我们可以通过不停找增广路来增加匹配中的匹配点和匹配边。找不到增广路时,达到最大匹配这就是(\(\color{red} {增广路定理}\))。匈牙利算法便是这么做的

题目描述:
给定一个二分图 G,即分左右两部分,各部分之间的点没有边连接,要求选出一些边,使得这些边没有公共顶点,且边的数量最大。

学会怎么应用即可

模版

struct augment_path {
  vector<vector<int> > g;
  vector<int> pa;  // 匹配
  vector<int> pb;
  vector<int> vis;  // 访问
  int n, m;         // 两个点集中的顶点数量
  int dfn;          // 时间戳记
  int res;          // 匹配数

  augment_path(int _n, int _m) : n(_n), m(_m) {
    assert(0 <= n && 0 <= m);
    pa = vector<int>(n, -1);
    pb = vector<int>(m, -1);
    vis = vector<int>(n);
    g.resize(n);
    res = 0;
    dfn = 0;
  }

  void add(int from, int to) {
    assert(0 <= from && from < n && 0 <= to && to < m);
    g[from].push_back(to);
  }

  bool dfs(int v) {
    vis[v] = dfn;
    for (int u : g[v]) {
      if (pb[u] == -1) {
        pb[u] = v;
        pa[v] = u;
        return true;
      }
    }
    for (int u : g[v]) {
      if (vis[pb[u]] != dfn && dfs(pb[u])) {
        pa[v] = u;
        pb[u] = v;
        return true;
      }
    }
    return false;
  }

  int solve() {
    while (true) {
      dfn++;
      int cnt = 0;
      for (int i = 0; i < n; i++) {
        if (pa[i] == -1 && dfs(i)) {
          cnt++;
        }
      }
      if (cnt == 0) {
        break;
      }
      res += cnt;
    }
    return res;
  }
};

来一个例题
C - 2D Plane 2N Points
1.用两重循环遍历所有的点,把合法的点放进去,相当于把这两个点连起来建立边,然后就是套上述点模版

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
#define allr(v) v.rbegin(),v.rend()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};

struct augment_path {
  vector<vector<int> > g;
  vector<int> pa;  // 匹配
  vector<int> pb;
  vector<int> vis;  // 访问
  int n, m;         // 两个点集中的顶点数量
  int dfn;          // 时间戳记
  int res;          // 匹配数

  augment_path(int _n, int _m) : n(_n), m(_m) {
    assert(0 <= n && 0 <= m);
    pa = vector<int>(n, -1);
    pb = vector<int>(m, -1);
    vis = vector<int>(n);
    g.resize(n);
    res = 0;
    dfn = 0;
  }

  void add(int from, int to) {
    assert(0 <= from && from < n && 0 <= to && to < m);
    g[from].push_back(to);
  }

  bool dfs(int v) {
    vis[v] = dfn;
    for (int u : g[v]) {
      if (pb[u] == -1) {
        pb[u] = v;
        pa[v] = u;
        return true;
      }
    }
    for (int u : g[v]) {
      if (vis[pb[u]] != dfn && dfs(pb[u])) {
        pa[v] = u;
        pb[u] = v;
        return true;
      }
    }
    return false;
  }

  int solve() {
    while (true) {
      dfn++;
      int cnt = 0;
      for (int i = 0; i < n; i++) {
        if (pa[i] == -1 && dfs(i)) {
          cnt++;
        }
      }
      if (cnt == 0) {
        break;
      }
      res += cnt;
    }
    return res;
  }
};



signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int n;cin>>n;
    pii a[105],b[105];
    for(int i=0;i<n;i++) cin>>a[i].x>>a[i].y;
    for(int i=0;i<n;i++) cin>>b[i].x>>b[i].y;
    
    augment_path ans(n,n);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(a[i].x<b[j].x&&a[i].y<b[j].y) ans.add(i,j);
        }
    }
    cout<<ans.solve()<<endl;
    
    return 0;
}

标签:二分,无权,匹配,增广,int,vector,path
From: https://www.cnblogs.com/swjswjswj/p/18309291

相关文章

  • C# 使用模式匹配的好处,因为好用所以推荐~
    类型检查和转换:当你需要检查对象是否为特定类型,并且希望在同一时间内将其转换为那个类型时,模式匹配提供了一种更简洁的方式来完成这一任务,避免了使用传统的as和is操作符后还需要进行额外的null检查。复杂条件逻辑:在处理复杂的条件逻辑时,特别是涉及到多个条件和类型的情况下,使......
  • 20240718二分图
    一.基础概念1.定义:如果一个图的所有顶点可以被分成两个集合U和V,使得每条边连接的两个顶点都分别属于两个不同的集合,那么这个图就是一个二分图(BipartiteGraph)。2.性质:每个偶环都是二分图如果一个二分图中存在奇环,则它不是二分图。二.霍尔定理前言:在hloj上有这个内容,不知......
  • 代码随想录二刷复习(二分法)
    二分法模板:1:左闭右闭区间写法第一种写法,我们定义target是在一个在左闭右闭的区间里,也就是[left,right](这个很重要非常重要)。区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left,right]区间,所以有如下两点:while(left<=right)要使用<=,因为left==rig......
  • day1 二分查找(及其进阶)和移除元素的双指针法
    基础概念算法的单调性:问题的规模随着算法的推进不断缩减(如704中开始的查找区间是[lo,hi),随着循环的进行,问题规模确实在不断的缩小)算法的不变性:在初始状态下自然满足,当问题的有效规模缩减为0时,不变性应该随即等于正确性。(如704中开始的查找区间是[lo,hi),最终要么直接命中,要么......
  • 如何使用QCompleter和QLineEdit实现支持模糊匹配的搜索栏
    最近需要用Qt实现搜索栏,类似于浏览器的搜索栏,需要支持模糊搜索并实时显示匹配的选项。接下任务后,迅速入门Qt.本来准备魔改QComboBox,但始终处理不好用户输入的焦点,最终效果并不好。后来了解到,QLineEdit中支持QCompleter,QCompleter就是用来实现补全提示的。QCompleter支持行内补......
  • 力扣第十题——正则表达式匹配(动态规划化的运用)(附思路讲解、完整代码及知识点精炼)
    题目介绍给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。'.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。 示例1:输入:s="aa",p="a"输出:false解......
  • 二分图相关
    %\(\rm\color{red}{L}\color{black}{BY}\)学长。0.定义:二分图:二分图是一张图\(G=(V,E)\),其中点集\(V\)可以分成两个部分\((V1,V2)\),满足\(V1\capV2=\emptyset,V1\cupV2=V\),且\(V1,V2\)中均没有边,即对于\(\foralle\inE,e=(v_i,v_j)\),均有\(......
  • OpenCV开发笔记(七十八):在ubuntu上搭建opencv+python开发环境以及匹配识别Demo
    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140435870长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…OpenCV开发专栏......
  • 由于安装多个jdk导致出现java以及javac版本不匹配问题
    之前由于下载了多个版本的jdk版本,导致了在运行java程序时出现了报错thisversionoftheJavaRuntimeonlyrecognizesclassfileversionsupto52.0报错信息大概为版本不匹配,查看了java以及javac的版本,发现一个是18,一个是20,所以查看解决方法,实现版本匹配一开始全在修改环......
  • 机器学习策略篇:详解处理数据不匹配问题(Addressing data mismatch)
    处理数据不匹配问题如果您的训练集来自和开发测试集不同的分布,如果错误分析显示有一个数据不匹配的问题该怎么办?这个问题没有完全系统的解决方案,但可以看看一些可以尝试的事情。如果发现有严重的数据不匹配问题,通常会亲自做错误分析,尝试了解训练集和开发测试集的具体差异。技术上......