二分图模型即状态整理

二分图首先是个无向图。

主要有以下几类问题:

1.二分图,不存在奇数环,染色法不存在矛盾

2.匈牙利算法,匹配,最大匹配,匹配点,增广路径

3.最小点覆盖,最大独立集,最小路径点覆盖,最小路径重复点覆盖

        最大匹配数=最小点覆盖=总点数-最大独立集=总点数-最小路径覆盖

(以下两种一般不用二分图来写)

4.最优匹配(达到最大匹配的情况下,边权和的最大值),KM算法(最小费用流)

5.多重匹配(每个点可以匹配多个点)(最大流)

1.二分图 = 不存在奇数环 = 染色法不存在矛盾

证明比较简单,可以自行搜索。

染色法模板:


bool dfs(int u, int c)
{color[u] = c;for (int i = h[u]; ~i; i = ne[i]){int j = e[i];if (color[j])//如果j已经染色,判断是否有矛盾{if (color[j] == c) return false;//如果有矛盾那么判否}else //如果没有染色,那么对j染色,判断往下染的时候是否会出现矛盾{if (dfs(j, 3 - c)) return false;}}return true;
}

257. 关押罪犯(257. 关押罪犯 - AcWing题库)

思路:首先我们注意到,需要将所有罪犯分到两个监狱中去,那么联想到二分图,二分图的要求就是边全部在两个集合之间,集合内部没有边,但是这里显然不能保证图是符合要求的,但是我们要求的是最大值最小,所以考虑二分,对于一个二分值,如果小于等于这个二分值的可以分进一个监狱,否则就必须分进两个监狱,那么从二分图的角度来看,相当于只保留了大于二分值的边。那么我们只需要判断这些被保留的边是否可以构成一个二分图,就可以判断当前的二分值是否有效了。如果可以构成二分图,显然这么分是可以的,如果不能构成二分图,那么就需要将二分值往上调一调,因为这样的话留下的边就更少了,产生矛盾的概率也更小了。

#include<bits/stdc++.h>
using namespace std;
const int N=20010,M=200010;
int h[N],e[M],ne[M],w[M],idx;
int n,m;
int color[N];
void add(int a,int b,int c)
{w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int u,int c,int mid)
{color[u]=c;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(w[i]<=mid) continue;if(color[j]){if(color[j]==c) return 0;}else {if(!dfs(j,3-c,mid)) return 0;}}return 1;
}
bool check(int mid)
{memset(color,0,sizeof color);for(int i=1;i<=n;i++){if(!color[i]){if(!dfs(i,1,mid)) return 0;}}return 1;
}
int main()
{scanf("%d%d",&n,&m);memset(h,-1,sizeof h);for(int i=1;i<=m;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);add(a,b,c),add(b,a,c);}int l=0,r=1e9;while(l<r){int mid=(l+r)/2;if(check(mid)) r=mid;else l=mid+1;}cout<<l;
}

2.匈牙利算法,匹配,最大匹配,匹配点,增广路径

匈牙利算法就是从二分图中查找最大匹配的算法。

匹配指二分图中一组没有公共点的边;

最大匹配是指边的数量最多的一组匹配

匹配点指的是在匹配中的点

增广路径:从一个非匹配点沿着非匹配边、匹配边、非匹配边、匹配边、...,最后走到另一个集合中的一个非匹配点。得到的路径是一个增广路径。增广路径是可以取代当前的匹配。

最大匹配等价于不存在增广路径

 找最大匹配用的是匈牙利算法,时间复杂度最坏O(nm),但一般不会到这个值。

匈牙利算法的实现思路是:遍历一个点集中的每个点,为每个点找一个匹配,如果找到的点还没有被匹配过,那么就将找到的点的匹配记为当前点,否则就去看能否为这个点的匹配点找一个新的匹配,注意新的匹配不能是这个点,所以在搜到这个点的时候需要标记以下。每一次开始查找的时候所有点都是没有标记的,标记只是在这一轮查找中这个点不能用,但是下一轮就可以用了。因为从一个点集找,所以我们建单向边即可。

861. 二分图的最大匹配(活动 - AcWing)

#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=100010;
int n1,n2,m;
int h[N],e[M],ne[M],idx;
int st[M],match[M];
void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool find(int u)
{for(int i=h[u];~i;i=ne[i]){int j=e[i];if(st[j]) continue;st[j]=1;if(!match[j]||find(match[j])) {match[j]=u;//这里要记得分配return 1;}}return 0;
}
int main()
{scanf("%d%d%d",&n1,&n2,&m);memset(h,-1,sizeof h);while(m--){int a,b;scanf("%d%d",&a,&b);add(a,b);}int c=0;for(int i=1;i<=n1;i++){memset(st,0,sizeof st);if(find(i)) c++;}cout<<c;
}

372. 棋盘覆盖(活动 - AcWing) 

思路:这里可能会想到用状态压缩来做,但是N太大了,2^100,一定会超时。所以我们需要换个思路。

这题其实有个特别巧妙地地方,我们将横纵坐标之和为奇数地称为奇点,为偶数的称为偶点,仔细观察可以放的位置,占据的都是连续的两个点,或横或竖,也就是一个奇点一个偶点,再加上不能重复,那么不就是在奇点和偶点两个集合之间找最大匹配嘛,分析到这里就很简单了,我们从奇点集去找偶点集的匹配即可。

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> pii;
const int N=120;
int n,m;
pii match[N][N];
int g[N][N],st[N][N];
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
bool find(int x,int y)
{for(int u=0;u<4;u++){int a=x+dx[u],b=y+dy[u];if(a<=0||a>n||b<=0||b>n) continue;if(g[a][b]||st[a][b]) continue;st[a][b]=1;pii t=match[a][b];if(t.x==-1||find(t.x,t.y)) {match[a][b]={x,y};return 1;}}return 0;
}
int main()
{scanf("%d%d",&n,&m);while(m--){int a,b;scanf("%d%d",&a,&b);g[a][b]=1;}memset(match,-1,sizeof match);int c=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if((i+j)%2==0 || g[i][j]) continue; memset(st,0,sizeof st);if(find(i,j)) c++;}}cout<<c;
}

 3.最小点覆盖,最大独立集,最小路径点覆盖,最小路径重复点覆盖

结论:最大匹配数=最小点覆盖=总点数-最大独立集=总点数-最小路径覆盖

最小点覆盖:选出最少的点,使得每条边的两个端点中至少有一个点被选出来了。

376. 机器任务(376. 机器任务 - AcWing题库)

思路:每个任务有两种完成的方式,那么如果在两种方式之间连一条边,那么就会得到一个二分图,相当于要求这个二分图的最小点覆盖。因为任意一条边至少有一个端点要被选。

对了要注意一下,初始为0,所以如果a或者b为0的话,可以直接执行,不用算到后面重启中去。

#include<bits/stdc++.h>
using namespace std;
const int N=120,M=1010;
int n,m,k;
int h[N],e[M],ne[M],idx;
int st[N],match[N];
void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool find(int u)
{for(int i=h[u];~i;i=ne[i]){int j=e[i];if(st[j]) continue;st[j]=1;if(match[j]==-1||find(match[j])){match[j]=u;return 1;}}return 0;
}
int main()
{while(~scanf("%d",&n)){if(!n) break;scanf("%d%d",&m,&k);memset(h,-1,sizeof h);memset(match,-1,sizeof match);while(k--){int c,a,b;scanf("%d%d%d",&c,&a,&b);if(!a||!b) continue;//最初为0add(a,b);}int c=0;for(int i=1;i<=n;i++){memset(st,0,sizeof st);if(find(i))c++;}printf("%d\n",c);}}

 最大独立集:从图中选出最多的点,使得任意两点之间没有边

最大团:从图中选出最多的点,使得任意两点之间都有边

在二分图中,求最大独立集 => 去掉最少的点将所有边都覆盖点 <=> 最小点覆盖 <=> 最大匹配

最大独立集=n-最大匹配

378. 骑士放置(378. 骑士放置 - AcWing题库)

这里不能互相攻击到,那么我们将可以互相攻击的点之间连边,得到一张图,那么需要求的就是最大独立集,因为选出的点两两之间没有边。然后还需要确定的一个问题就是这张图是否是二分图。对于一个点,它能攻击到的点与它的横纵左边之间的总差值应该是一个奇数,那么就会改变奇偶性,那么我们按照奇点偶点分成两个集合,那么就是一个二分图。类似于棋盘覆盖那道题,问题就解决了。

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> pii;
const int N=120;
int n,m,t;
pii match[N][N];
int g[N][N],st[N][N];
int dx[]={1,1,-1,-1,2,2,-2,-2};
int dy[]={2,-2,2,-2,1,-1,1,-1};
bool find(int x,int y)
{for(int u=0;u<8;u++){int a=x+dx[u],b=y+dy[u];if(a<1||a>n||b<1||b>m) continue;if(g[a][b]||st[a][b]) continue;st[a][b]=1;pii t=match[a][b];if(t.x==-1||find(t.x,t.y)) {match[a][b]={x,y};return 1;}}return 0;
}
int main()
{scanf("%d%d%d",&n,&m,&t);for(int i=1;i<=t;i++){int a,b;scanf("%d%d",&a,&b);g[a][b]=1;}memset(match,-1,sizeof match);int c=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if((i+j)%2 || g[i][j]) continue; memset(st,0,sizeof st);if(find(i,j)) c++;}}cout<<n*m-t-c;//坏点是不能被选的,所以不包含在图中,我们是要从图中选点,图中的总点数-最大匹配数
}

 最小(路径)点覆盖:在DAG(有向无环图)中用最少的互不相交(点边都不重复)的路径将所有点覆盖住。

这里需要用到拆点:对于原来的每个点建立一个新点,原点作为出点,新点作为入点。那么相当于就产生一个二分图。那么最小点覆盖=n(一边的点数)-m(最大匹配数)

因为互不相交,所以每个点只有一个出度和一个入度,那么在新图中就对应一个匹配。

路径的终点对应左侧一个非匹配点,那么一个非匹配点就对应一条路径。

所以求最小路径数,就是求左侧最少非匹配点的数量,那么匹配点最多,那么就是最大匹配。

如果可以相交,那么就是最小路径重复点覆盖。

求原有向图的传递闭包得到一个新图,求新图的最小路径点覆盖。

379. 捉迷藏(379. 捉迷藏 - AcWing题库)

相当于给定一个有向无环图,从中选出一些点,使得任意两点之间都不能从一个走到另一个。

我们假设图中有m个最小路径重复点覆盖,那么显然我们只能在一条路径上选一个点,否则选的点就是可达的。因为这里只要可达就可以相互看到,所以需要求最小路径重复点覆盖。

传递闭包可以用Floyd算法来求。

#include<bits/stdc++.h>
using namespace std;
const int N=210;
int n,m;
int st[N],g[N][N],match[N];
int find(int u)
{for(int i=1;i<=n;i++){if(g[u][i]==0) continue;if(st[i]) continue;st[i]=1;if(!match[i]||find(match[i])){match[i]=u;return 1;}}return 0;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);g[a][b]=1;}for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){g[i][j]|= g[i][k]&g[k][j];}}}int res=0;for(int i=1;i<=n;i++){memset(st,0,sizeof st);if(find(i)) res++;}cout<<n-res;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/694025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在VS里使用C#制作窗口应用

新建项目 创建项目的时候搜索net&#xff0c;选择这个。 打开应该是这样 第一个控件 选择公共控件 - PictureBox - 拖入Form 在Image处选择上传本地资源&#xff0c;建议上传一个小一点的图片。 修改一下尺寸。 ctrls 保存 从“属性”切换到“事件” 双击Click事件…

kubernetes日志收集 fluent-operator 动态索引名的实现

文章目录 按照服务名区分索引名1.修改fluent-operator&#xff0c;让其支持logstash_prefix_key2.让它能获取app name作为服务名3. 拼接索引名4. 应用变更 发自个人博客&#xff1a; https://uublog.com/article/20230510/kubernetes-fluent-operator-dynamic-index-name/ 日志…

【银河商学】大蓝短视频学习01——定位,定江山

【银河商学】大蓝短视频学习01 定位,定江山一、 变现定位抖音变现的五大模式知识付费直播短视频带货星图广告实体引流招商加盟二、赛道定位赛道选择- 可以多个,有主赛道,有副赛道1. 资源2. 能力3. 兴趣爱好定位,定江山 变现定位——钱则呢么转赛道定位——内容方向则呢么定…

【Jenkins+Gitlab自动化部署配置】

【JenkinsGitlab自动化部署配置】 以下为整理当初参照的博客 阿里云云服务器 ECS 手动搭建GitLab避坑教程 https://blog.csdn.net/Tanasha114/article/details/121602478博客文中的镜像源地址已换 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/Gitlab忘记root用…

DBSCAN密度聚类介绍 样本点 样本集合 半径 邻域 核心对象 边界点 密度直达 密度可达 密度相连

DBSCAN密度聚类介绍 样本点 样本集合 半径 邻域 核心对象 边界点 密度直达 密度可达 密度相连 简介概念定义原理DBSCAN的优点DBSCAN的缺点小尝试制作不易&#xff0c;感谢三连&#xff0c;谢谢啦 简介 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications wi…

【算法】动态规划1,最小花费爬楼梯,解码方法

一、动态规划简介 动态规划 , 英文名称 Dynamic Programming , 简称 DP , 不是具体的某种算法 , 是一种算法思想 ; 动态规划 , 没有具体的步骤 , 只有一个核心思想 ; 动态规划 的 核心思想 是 由大化小 , 大规模问题 使用 小规模问题 计算结果 解决 , 类似于 分治算法 ; 二、…

srs集群下行edge处理逻辑

官方关于源站集群的介绍&#xff1a; Origin Cluster | SRS 下行边缘是指观众端从边缘edge拉流&#xff0c;边缘edge回源到源站origin节点拉流&#xff0c;然后再 把流转给客户端 边缘处理类SrsPlayEdge 当服务器收到播放请求时&#xff0c;创建对应的consumer消费者。在创…

C#_字段 属性 常量与只读

字段(旧称成员变量) 字段定义在类中&#xff08;定义在函数等代码体中的变量称为局部变量&#xff09;实例字段与该对象关联&#xff08;类实例化之后才可调用&#xff09;静态字段与该类型关联&#xff08;为该类型的特征&#xff0c;可直接调用&#xff0c;无需具体至对象&am…

Docker后台启动镜像,如何查看日志信息

执行 docker run -d -p 9090:8080 core-backend-image 命令后&#xff0c;Docker 会在后台运行一个新的容器实例&#xff0c;并映射宿主机的 9090 端口到容器的 8080 端口。要查看启动的容器日志&#xff0c;您需要先获取容器的 ID 或名称&#xff0c;然后使用 docker logs 命令…

令牌颁发与管理服务

技术背景 在分布式系统中,令牌(Token)被广泛应用于身份认证成功后对系统的访问控制。在本文中,我们实现了一个简单的令牌颁发与管理服务,其中包含访问令牌(AccessToken)和刷新令牌(RefreshToken)两种类型的令牌。 功能需求 颁发刷新令牌和访问令牌验证和管理访问令牌…

Linux系统之iptables应用SNAT与DNAT

一、SNAT&#xff1a; 1.应用环境 局域网主机共享单个公网IP地址接入Internet &#xff08;私有IP不能在Internet中正常路由&#xff09; 2.SNAT原理 源地址转换&#xff0c;根据指定条件修改数据包的源IP地址&#xff0c;通常被叫做源映谢数据包从内网发送到公网时&#x…

CDH 6.x版本 HBase基础调优参数

参数默认值调优值参数解释hbase.regionserver.handler.count30120指定了每个RegionServer处理请求的最大线程数hbase.regionserver.metahandler.count30120指定了在RegionServer中处理Meta表的请求数量hbase.client.retries.number1015HBase客户端重试操作的最大次数hbase.hsto…

Java中的Enum

Enum是一个特殊的类 Java 中的枚举类型&#xff08;enum&#xff09;实际上是一种特殊的类。enum编译后是一个特殊的类&#xff08;有些类似单例模式&#xff09;这些实例在声明时就被创建&#xff0c;并在整个应用程序的生命周期中只存在一个实例。 enum 用于定义包含固定数量…

Fiddler与wireshark使用

Fiddler解决三个问题 1、SSL证书打勾&#xff0c;解析https请求 2、响应回来乱码&#xff0c;不是中文 3、想及时中止一下&#xff0c;查看实时的日志 4、搜索对应的关键字 问题1解决方案&#xff1a; 标签栏Tools下 找到https&#xff0c;全部打勾 Actions里面 第一个 t…

项目的一些难点

1.不用redis?分布式锁&#xff0c;如何防止用户重复点击&#xff1f; 1.乐观锁 乐观锁是一种在数据库层面上避免并发冲突的机制。它通常通过在数据库记录中添加一个版本号&#xff08;或时间戳&#xff09;来实现。每次更新记录时&#xff0c;都会检查版本号是否与数据库中的…

Luogu P6175 无向图的最小环问题 题解 Floyd

题目链接&#xff1a;Luogu P6175 无向图的最小环问题 题目描述&#xff1a; 给定一张带权无向图&#xff0c;求出经过至少三个不同的点的最小环&#xff0c;环的大小由经过的边权和决定。 题解&#xff1a; 我们首先回到Floyd算法&#xff0c;在Floyd算法中&#xff0c;我们定…

从输入url到页面显示中间发生了什么

文章目录 整体概述URL释义用户输入缓存处理域名解析IP 地址什么是域名解析浏览器查找域名对应IP小结 TCP 三次握手握手时序三次握手数据包分析为什么需要三次握手 HTTP 请求HTTP 响应服务器MVC 后台处理阶段http 响应报文 TCP 四次挥手浏览器渲染 整体概述 浏览器输入 URL 到页…

如何搭建Facebook直播网络?

在当今数字化时代&#xff0c;Facebook直播已经成为了一种极具吸引力的社交形式&#xff0c;为个人和企业提供了与观众直接互动的机会&#xff0c;成为推广产品、分享经验、建立品牌形象的重要途径。然而&#xff0c;对于许多人来说&#xff0c;搭建一个稳定、高质量的 Faceboo…

创意办公:专注 ONLYOFFICE,探索办公新境界

一.ONLYOFFICE 介绍 ONLYOFFICE 是一个基于 Web 的办公套件&#xff0c;提供了文档处理、电子表格和演示文稿编辑等功能。它被设计为一个协作工具&#xff0c;支持多人实时协作编辑文档&#xff0c;并且可以在本地部署或者作为云服务使用。 二.ONLYOFFICE 特点和功能 以下是 …

Unity调用文心-ERNIE-Bot-turbo

参考文章 ERNIE-Bot-turbo - 千帆大模型平台 | 百度智能云文档 (baidu.com) 错误码 - 千帆大模型平台 | 百度智能云文档 (baidu.com) private readonly string apiKey "";private readonly string secretKey "";private readonly string tokenUrl &q…