二分图匹配(二)

文章目录

  • 例题:
    • NC20483 [ZJOI2009]假期的宿舍
      • 题目描述:
      • 题解:
    • NC51316 Going Home
      • 题目描述:
      • 题解:
    • NC107638 poj3041 Asteroids
      • 题目描述:
      • 题解:
    • NC20472 [ZJOI2007]矩阵游戏
      • 题目描述:
      • 题解:
    • NC110335 CF387D George and Interesting Graph
      • 题目:
      • 题解:
      • 代码:
      • 代码:
    • NC131152 Gym 101873F Plug It In
      • 题意:
      • 题解:
      • 代 码:
    • NC112788 CF981F Round Marriage
      • 题目:
      • 题解:
      • 答案:

例题:

NC20483 [ZJOI2009]假期的宿舍

题目描述:

学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题。比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识。我们假设每个人只能睡和自己直接认识的人的床。那么一个解决方案就是 B 睡 A 的床而 C 睡 B 的床。
而实际情况可能非常复杂,有的人可能认识好多在校学生,在校学生之间也不一定都互相认识。我们已知一共有 n 个人,并且知道其中每个人是不是本校学生,也知道每个本校学生是否回家。
问是否存在一个方案使得所有不回家的本校学生和来看他们的其他人都有地方住。

题解:

构造二分图
一边是
本校学生有相应的床
一边是
要到学校的人
床与人构造边
在这里插入图片描述
• 左集合为所有需要床的人,右集合为所有的床
• 当第x个人可以睡第y张床(即认识第y个床的主人)那么就可以连边
• 求出最大匹配即可
详细题解+代码看

NC51316 Going Home

题目描述:

n 个小人回到 n 间房子,要求一对一,告诉每个人的位置和每个房子的位置,问n个人移动的总距离最少是多少

题解:

最小权值匹配模板
在这里插入图片描述
将所有值取相反数,然后跑一遍最优权值匹配模板

NC107638 poj3041 Asteroids

题目描述:

网格图中有若干个陨石,每次发射武器可以打掉某一行或某一列的所有陨石,求打完所有陨石的最少次数
在这里插入图片描述

题解:

首先,贪心的打星球最多的行/列有反例,如:
0 0 0 0
1 1 0 0
1 0 1 0
1 0 0 1
正解:
我们把行和列抽象为点,把陨石抽象为边,即当(x,y)有一个陨石的时候 ,将左边的第x个
点与右边的第y个点连边
• 最后是要找到最少的点(行/列)来覆盖掉所有的边(陨石)
• 也就是二分图的最小点覆盖!
最小点覆盖:在二分图中选尽量少的点覆盖所有的边
我们将问题转化为选左右最少数量的点可以覆盖所有边
而 最小点覆盖=最大匹配
在这里插入图片描述
比如例子:
0 0 0 0
1 1 0 0
1 0 1 0
1 0 0 1
在这里插入图片描述

NC20472 [ZJOI2007]矩阵游戏

题目描述:

• 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。
矩阵游戏在一个N *N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。
• 每次可以对该矩阵进行两种操作:
• 行交换操作:选择 矩阵的任意两行,交换这两行(即交换对应格子的颜色)
• 列交换操作:选择矩阵的任意行列,交换这两列(即交换 对应格子的颜色)
• 游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。
• 对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!!于是小Q决定写一个程序来判断这些关卡是否有解。
• N<=200

题解:

问题可以转化成:
• 每一行只保留一个黑色的点,且让这些黑色的点所在的列各不相同(即覆盖到每一列)
• 把行列抽象成点,分别为左集合和右集合
• 把黑点抽象成边,连接对应的行和列
• 看最大匹配是不是等于n,如果等于n就可行

NC110335 CF387D George and Interesting Graph

题目:

给你一个无重边的有向图,你每次操作可以加一条边或者删一条边,求让图变成一个“有趣
图”的最小操作次数
• “有趣图”,满足:
• 存在一个中心结点v,它和其他每个点都有双向边,且和自身有自环。
• 除了中心结点之外,其他结点的入度和出度都为2。 • 2 ≤ n ≤ 500, 1 ≤ m ≤ 1000

题解:

题目要求的其他节点的入度和出度都为2,因为中心节点要与其他点都有一条边,去除中心节点 v之后(以及v所关联的边),剩下所有点组成环(一个或者多个不想交的环,因为环上的点入度出度都为1)
N不大,考虑枚举中心点u • 分类讨论:
• 和u有关的边:
• u的自环 ——没有就+1条,有就不管了
• u到每一个点的出边和入边——如果没有就加上这1条,如果有就不管

和u无关的边

将每个点的入度与出度分为左集合和右集合

• 当我们把和u有关的边都删掉以后,每个点的出度和入度都应该是1 • 在这种情况下我们要操作的次数最小,也就是保留尽量多的原来的边——把每个点拆成
入点和出点,所有的入点和出点分别为左集合和右集合,求出来的最大匹配就是能保留
的边,其他的边要删掉;而如果最大匹配数不等于非中心节点数,显然就还需要加边
(需要将二分图匹配加成满配才能满足每个点入度1出度1,这样原图也就变成了一个环或者多个不相交的环。)

代码:

目前为WA,没发现哪里错了。。。感觉应该没问题的

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=600;
const int mod=500;
int g[maxn][maxn];
int a[1030][1030];
int tot=0;
int vis[maxn];
int link[maxn];
int n,m;
int maxmatch(int x)
{for(int i=1+n;i<=n+n;i++){if(a[x][i]==0||vis[i])continue;vis[i]=1;if(link[i]==0||maxmatch(link[i])){link[i]=x;return 1;}}return 0;
}
int main()
{cin>>n>>m;for(int i=1;i<=m;i++){int x,y;cin>>x>>y;g[x][y]=1;}int maxx=0x7f;for(int i=1;i<=n;i++){memset(link,0,sizeof(link));tot=0;if(g[i][i]!=1)tot++;for(int j=1;j<=n;j++){if(j==i)continue;if(g[i][j]==0)tot++;if(g[j][i]==0)tot++;}		int sum=0;int ans=0;for(int j=1;j<=n;j++){if(j==i)continue;for(int k=1;k<=n;k++){if(k==i)continue;if(g[j][k]){a[j][k+n]=1;a[k+n][j]=1;ans++;}}}//int op=0;for(int j=1;j<=n;j++){if(j==i)continue;memset(vis,0,sizeof(vis));sum+=maxmatch(j);}tot+=ans-sum;tot+=n-1-sum;maxx=min(maxx,tot);}cout<<maxx;
}

网上找的AC代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int match[600];
int vis[600];
int a[600][600];
int x[4545];
int y[4545];
int n,m;
int find(int u)
{for(int i=1;i<=n;i++){if(a[u][i]==1&&vis[i]==0){vis[i]=1;if(match[i]==-1||find(match[i])){match[i]=u;return 1;}}}return 0;
}
int Slove(int u)
{int ans=0,tot=0;memset(a,0,sizeof(a));for(int i=1;i<=m;i++)a[x[i]][y[i]]=1;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(a[i][j]==1&&(i!=u)&&(j!=u))tot++;if(a[i][j]==0&&(i==u||j==u)){ans++;}if(i==u||j==u)a[i][j]=0;}}memset(match,-1,sizeof(match));int output=0;for(int i=1;i<=n;i++){memset(vis,0,sizeof(vis));if(i==u)continue;if(find(i))output++;}ans+=n-1-output;ans+=tot-output;return ans;
}
int main()
{while(~scanf("%d%d",&n,&m)){for(int i=1;i<=m;i++){scanf("%d%d",&x[i],&y[i]);}int ans=0x3f3f3f3f;for(int i=1;i<=n;i++){int tmp=Slove(i);ans=min(ans,tmp);}printf("%d\n",ans);}
}

代码:

NC131152 Gym 101873F Plug It In

评测地址

题意:

有m个插座,n个电器,每个插座最多可连接一个电器。另外有一个插线板,可以使得一个插座连接三个电器,给出每个插座能插的电器,问最多能插电器的个数是多少。
• N,m<=1500, k(边数)<=75000

题解:

先不考虑插线板 ——二分图最大匹配
• 插线板会使得某个插头被复制两份
• ——枚举插头然后加倍再跑最大匹配行不行?
• 会tle
• 因为插一个插头其实只是加了两个点——先把原图的最大匹配结果保留下来
• 然后每次在这个结果上加两个点,给它两找增广路即可。

代 码:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=1508;
int a[maxn][maxn];
int vis[maxn];
int link[maxn];
int link1[maxn];
int n,m,k;
int maxmatch(int x)
{for(int i=1;i<=m;i++){if(vis[i]||a[x][i]==0)continue;vis[i]=1;if(link[i]==0||maxmatch(link[i])){link[i]=x;return 1;}}return 0;
}
void init()
{for(int i=1;i<=m;i++){link[i]=link1[i];}
}
int main()
{cin>>n>>m>>k;//while(scanf("%d%d%d", &n, &m, &k) == 3){for(int i=1;i<=k;i++){int x,y;cin>>x>>y;a[x][y]=1;//a[y][x]=1;}int sum=0;for(int i=1;i<=n;i++){memset(vis,0,sizeof(vis));sum+=maxmatch(i);}//	cout<<"sum="<<sum<<endl;int maxx=0;for(int i=1;i<=m;i++){link1[i]=link[i];}for(int i=1;i<=n;i++){init();int tot=0;for(int j=1;j<=2;j++){memset(vis,0,sizeof(vis));tot+=maxmatch(i);}maxx=max(maxx,tot);//cout<<"tot="<<tot<<endl;//	cout<<"sum="<<sum<<endl;}cout<<sum+maxx<<endl;}}

NC112788 CF981F Round Marriage

题目:

• n个新郎和n个新娘围成一个环,环的长度为L,给出所有新郎可以站的位置和新娘可以站的位置,将新郎新娘安排到这些位置上,最 小化每一对新郎和新娘距离的最大值。
• 1≤n≤2*105 ,1 ≤ L≤ 109

题解:

• 二分答案
• 每次只添加男女之间不超过mid的边,求最大匹配
• 会tle
• Hall定理:对于一个二分图,如果对于左边任意子集S,其对应边连接了一个右边的点集T,
都有|S|≤|T|,那么这个二分图有完美匹配。(充要)
在这里插入图片描述
对于本题来说,左集合的点x,在右集合能匹配的点刚好是一个区间,记为[Lx,Rx] • 因为当x增大的时候,对应的区间也是右移的,所以我们只需要看连续的左集合——左集合中
任意区间[a,b]都需要满足其对应区间[La,Rb]中的元素比他多
• 即b-a<=Rb-La
• 移项: b-Rb<=a-La
sum[b]:b点及以前新郎个数
sum2[b]:b点及以前新娘个数
x是第几个新郎,Lx,Ly是新娘的范围
再枚举a,b

二分答案,判mid是否合法
如何判断:如果是在直线上,那么遍历匹配即可
现在在环上,即既可以向前匹配也可以向后匹配,那么将环拆开,扩展成三倍

显然a和b的匹配边是不可能交叉的,因为交叉必定没有不交叉优
hall定理:二分图两个点集A,B,连续一段A的点对应连续一段B的点的 充要条件是 这些点对的匹配边之间不交叉
重要推论:二部图G中的两部分顶点组成的集合分别为X,Y, 若|X|=|Y|,
且G中有一组无公共端点的边,一端恰好组成X中的点,一端恰好组成Y中的点,则称二部图G中存在完美匹配

有了这个定理,就可以用在判定上:a的点集对应b点集的连续一段,即b的n个点也是连续的,因为之前已经确定匹配边不交叉
先求出a[1]的范围[a[1]-mid,a[1]+mid]对应的能控制的b数组的范围[l1,r1]
那么a[2]的控制范围要和[l1+1,r1+1]交叉得到[l2,r2]
那么a[3]的控制范围要和[l2+1,r2+1]交叉得到[l3,r3]

…依次类推
可以这个区间长度只会减小不会变大

答案:

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
long long n,L,a[maxn],b[maxn<<2],c[maxn],m;int judge(int mid){//a[i]的控制区间是[a[i]-mid,a[i]+mid] int l=1,r=m;for(int i=1;i<=n;i++){while(a[i]-mid>b[l])++l;while(a[i]+mid<b[r])--r;if(l>r)return 0;++l,++r;} return 1;
}int main(){cin>>n>>L;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)cin>>c[i];sort(c+1,c+1+n);sort(a+1,a+1+n);for(int i=1;i<=n;i++)b[i]=c[i]-L;for(int i=1;i<=n;i++)b[i+n]=c[i];for(int i=1;i<=n;i++)b[i+2*n]=c[i]+L;m=3*n;int l=0,r=L,ans,mid;while(l<=r){mid=l+r>>1;if(judge(mid))ans=mid,r=mid-1;else l=mid+1;}cout<<ans<<'\n';
} 

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

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

相关文章

质数和分解(动态规划)

文章目录题目描述解析记忆化搜索代码无限背包代码thanks for reading&#xff01;题目描述 解析 很好的题 记忆化搜索 我一开始的思路就是记忆化搜索 为了不重复&#xff0c;搜索的时候规定拆出来一个数A后一会不能再拆比A更小的了 这样就不难写了 &#xff08;忽略我n^2的素…

【.NET Core项目实战-统一认证平台】第十章 授权篇-客户端授权

上篇文章介绍了如何使用Dapper持久化IdentityServer4&#xff08;以下简称ids4&#xff09;的信息&#xff0c;并实现了sqlserver和mysql两种方式存储&#xff0c;本篇将介绍如何使用ids4进行客户端授权。.netcore项目实战交流群&#xff08;637326624&#xff09;&#xff0c;…

内存管理(ybtoj-二叉堆)

文章目录题目描述解析代码题目描述 解析 这题感觉做的不错 不难看出&#xff0c;要维护一个空闲的优先队列&#xff0c;在每次申请时弹出编号最小的 但是对判断当前哪些被访问的内存重新进入空闲状态是一个难题 最简单的办法是存起来每次扫一遍判断 但这样在极端数据时会TLE&…

[翻译]初试C# 8.0

原文地址: https://blogs.msdn.microsoft.com/dotnet/2018/12/05/take-c-8-0-for-a-spin/初试C# 8.0昨天我们宣布了Visual Studio 2019的第一个预览版&#xff08;使用Visual Studio 2019提高每个开发人员的工作效率&#xff09;和.NET Core 3.0&#xff08;宣布.NET Core 3预览…

上帝造题的七分钟(ybtoj-树状数组)

文章目录题目描述解析代码thanks for reading&#xff01;题目描述 解析 差点活活恶心死 搬砖题 &#xff08;其实细节没有那么多&#xff0c;还是代码能力太差&#xff09; 利用矩阵的二维差分 加上树状数组搞一搞 就完事了&#xff08;我实在不想再写了 &#xff09; 洛谷…

.NET Core微服务之路:让我们对上一个Demo通讯进行修改,完成RPC通讯

最近一段时间有些事情耽搁了更新&#xff0c;抱歉各位了。上一篇我们简单的介绍了DotNetty通信框架&#xff0c;并简单的介绍了基于DotNetty实现了回路&#xff08;Echo&#xff09;通信过程。我们来回忆一下上一个项目的整个流程&#xff1a;当服务端启动后&#xff0c;绑定并…

Visual Studio 2019 首个预览版本抢先看,有啥新功能?

微软在 Connect 2018 大会上发布Visual Studio 2019 第 1 个预览版本。该预览版本中展示了许多变更&#xff0c;从 IDE 的启动行为&#xff0c;到代码重构功能&#xff1b;从搜索功能的更多用法&#xff0c;到更好的大型项目导航。这个预览版本展现了微软希望尽全力帮助开发人员…

模板:网络流(Dinic算法)

文章目录1.网络最大流题目描述解析反悔边分层&#xff08;避免环流&#xff09;时间优化代码2.费用流描述解析代码1.网络最大流 洛谷P3376 题目描述 给出一个网络图&#xff0c;以及其源点和汇点&#xff0c;求出其网络最大流。 解析 网络流的思想就是在原有的基础上不断进…

NC51272 棋盘覆盖

题目&#xff1a; 给出一张nn(n≤100) 的国际象棋棋盘&#xff0c;其中被删除了一些点&#xff0c;问可以使用多少1*2的多米 诺骨牌进行掩盖。 题解&#xff1a; 先进行黑白染色&#xff0c;相邻的两个黑白就是一个骨牌&#xff0c;又因为一个格子不能放多个骨牌&#xff0c;…

微软推出 VS Code 新特性,为 TypeScript 和 JavaScript 用户提供 AI 辅助开发功能

除了开发人员非常喜欢的IntelliSense和代码完成之外&#xff0c;今年早些时候&#xff0c;微软还发布了IntelliCode&#xff0c;提供了一组 AI 辅助开发功能。VS Code 团队现在宣布了一项新的实验性扩展&#xff0c;将 IntelliCode 带给了 TypeScript 和 JavaScript 用户。VS C…

NC107617 poj3020 Antenna Placement

问题&#xff1a; n * m的矩阵&#xff0c;有一些障碍点&#xff0c;用12的骨牌覆盖所有非障碍点 (12骨牌可重叠&#xff0c;骨牌可越界&#xff0c;骨牌可延伸到障碍点) 问最少需要 多少个。 题解&#xff1a; • 尽量用一个骨牌覆盖两个格子&#xff0c;覆盖不了了再重叠使…

货车运输(洛谷P1967)(倍增)

传送门 文章目录题目描述题目解析代码题目描述 题目解析 本题如果告诉你&#xff0c;城市形成了一棵树&#xff0c;是不是就迎刃而解了呢? 本题的关键就是把稠密图转化为一片森林&#xff08;就是可能有很多棵树啦&#xff09; 怎么转化呢? 考虑哪些边是没用的 如果AB已经可…

.NET Core实战项目之CMS 第十一章 开发篇-数据库生成及实体代码生成器开发

上篇给大家从零开始搭建了一个我们的ASP.NET Core CMS系统的开发框架&#xff0c;具体为什么那样设计我也已经在第十篇文章中进行了说明。不过文章发布后很多人都说了这样的分层不是很合理&#xff0c;什么数据库实体应该跟仓储放在一起形成领域对象&#xff0c;什么ViewModel应…

第1节 连通性强连通、割点和桥(一)

文章目录无向图割点、桥、双连通分量Tarjan算法求割点和桥&#xff08;割边&#xff09;代码&#xff1a;边双连通分量 和 点双连通分量代码边双连通分量 和 点双连通分量 的缩点有向图的弱连通与强连通强连通分量Kosaraju算法Tarjan算法代码&#xff1a;无向图割点、桥、双连通…

连通性(相关练习)

文章目录NC20603 [ZJOI2007]最大半连通子图题目&#xff1a;题解&#xff1a;代码&#xff1a;NC50403 嗅探器题目&#xff1a;题解&#xff1a;代码&#xff1a;NC51269 Network of Schools题目&#xff1a;题解&#xff1a;代码&#xff1a;NC106972 Cow Ski Area题目&#x…

ASP.NET Core WebAPI中使用JWT Bearer认证和授权

为什么是 JWT BearerASP.NET Core 在 Microsoft.AspNetCore.Authentication 下实现了一系列认证, 包含 Cookie, JwtBearer, OAuth, OpenIdConnect 等,Cookie 认证是一种比较常用本地认证方式, 它由浏览器自动保存并在发送请求时自动附加到请求头中, 更适用于 MVC 等纯网页系统的…

网络流专题(最大流与费用流)(一)

流量网络 • 想要将一些水从S运到T&#xff0c;必须经过一些水站&#xff0c;链接水站的是管道&#xff0c;每条管道都有它的最大能容纳的水量&#xff0c;求最多S到T能流多少流量。 基本概念 • 这是一个典型的网络流模型。我们先了解网络流的有关定义和概念。 • 若有向图G(…

eShopOnContainers 看微服务 ①:总体概览

一、简介eShopOnContainers是一个简化版的基于.NET Core和Docker等技术开发的面向微服务架构的参考应用。该参考应用是一个简化版的在线商城/电子商务微服务参考示例应用。其包含基于浏览器的Web应用、基于Xamarin的Android、IOS、Windows/UWP 移动应用&#xff0c;以及服务端应…

网络流专题(最大流与费用流)例题总结

文章目录NC 106056 poj1459 Power Network题目大意&#xff1a;题解&#xff1a;NC213817 [网络流24题]最小路径覆盖问题题目&#xff1a;题解&#xff1a;例2&#xff1a;NC213818 [网络流24题]魔术球问题题目&#xff1a;题解&#xff1a;方法2&#xff1a;NC 213820 [网络流…

周期长度和(KMP)

文章目录题目描述解析问题总结代码题目描述 解析 我们可以看到 如果A是B的周期 那么B一定可以写成&#xff1a; A1A2A1 的形式 注意到&#xff1a;A1就是KMP中的公共前后缀 要使A最大&#xff0c;要使A1最短 也就是求最短公共前后缀 这怎么求呢&#xff1f; 我们注意到&#x…