二分图

组合数学实验——二分图匹配算法

不羁岁月 提交于 2020-04-15 15:39:56
【推荐阅读】微服务还能火多久?>>> 大一时候写的代码,忽然翻了出来.... 算法:组合数学中文第4版 机械工业出版社 P234 ID就先隐藏掉了 ////////////////////////////////////////////// // // // Project Name: matching // // // // Author: Victor Zhang // // // // ID: 21*****92 // // // // Create Date: March 31. 2009 // // // ////////////////////////////////////////////// #include <iostream> #include <iomanip> using namespace std; struct Node { int i;//col int j;//row int tag;//-1='*', 0=Empty, -2=Locked int link;//-1=Empty, 0=Locked bool flag;//search flag Node* down; Node* right; }; class Graph { private: Node* head; int row; int col; int num; bool

coci2018 题解

♀尐吖头ヾ 提交于 2020-04-06 18:23:23
plahte 给定一些矩形和一些有颜色的点,求每个矩形上有多少种颜色的点,保证矩形只有包含和不相交两种关系,规模 \(10^5\) 。 把每个矩形看成一个点,用扫描线建出森林,同时也顺便处理点。 然后做一个树上的集合转移,把儿子集合的元素并到父亲集合去。这个问题有树状数组的做法,但我试了一下轻重链剖分,写起来还是挺友好的。注意这里的重儿子选择标准不是节点个数,而是节点上颜色个数,这样复杂度算起来才是正确的。(一个log跑起来比两个log的标算慢 我也是很服气 ) san 给出一个长度小于等于 \(20\) 的二元组序列和一个数 \(k\) , \(k\) 的规模为 \(10^{10}\) ,第一个数代表高度,第二个数代表金币,求金币总和不小于 \(k\) 的不下降子序列个数。 折半搜索。将原序列分成 \([1,n/2],[n/2+1,n]\) 两个区间,以高度为关键字升序加入每一个点,显然后加入的且在后半部分的点都可以由前面加入的且在前半部分的点转移,数据结构维护值域上的区间和即可。 这题很好地证明了背包问题是NP难的? usmjeri 给出一棵树以及若干个限制条件,要求你把树定向成一个有向图,使得给出的限制中的每对点联通,求方案总数,规模 \(10^{5}\) 。 首先把问题转化为给边染色:对于每个限制 \(a_i,b_i\) ,给树上的边染色,令 \(c_i=lca(a_i,b

[最大流][匈牙利算法] 洛谷 P3386 二分图匹配

眉间皱痕 提交于 2020-03-23 18:45:39
题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 输出格式: 共一行,二分图最大匹配 输入输出样例 输入样例#1: 1 1 1 1 1 输出样例#1: 1 说明 n,m \leq 1000 n , m ≤ 1 0 0 0, 1 \leq u \leq n 1 ≤ u ≤ n, 1 \leq v \leq m 1 ≤ v ≤ m 因为数据有坑,可能会遇到 v>m v > m 的情况。请把 v>m v > m 的数据自觉过滤掉。 算法:二分图匹配 题解 看这题目也看着像板题,就是模板题,匈牙利、最大流两种做法 代码1 1 #include <cstdio> 2 #include <iostream> 3 #include <queue> 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 queue<int>Q; 7 struct edge {int to,from,v;}e[2001000]; 8 int n,m,num,cnt,ans,s,t,dis[1010*4],head[1010*4],cur[1010*4]; 9 void insert(int x,int y,int z) { e[++cnt]

P3386 【模板】二分图匹配(匈牙利&最大流)

牧云@^-^@ 提交于 2020-03-05 06:01:26
P3386 【模板】二分图匹配 题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 输出格式: 共一行,二分图最大匹配 输入输出样例 输入样例#1: 复制 1 1 1 1 1 输出样例#1: 复制 1 说明 n,m \leq 1000 n , m ≤ 1 0 0 0 , 1 \leq u \leq n 1 ≤ u ≤ n , 1 \leq v \leq m 1 ≤ v ≤ m 因为数据有坑,可能会遇到 v>m v > m 的情况。请把 v>m v > m 的数据自觉过滤掉。 算法:二分图匹配 code 匈牙利 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 7 using namespace std; 8 9 const int N = 1010; 10 int e[N][N],vis[N],resut[N]; 11 int n,m,E; 12 13 inline int read() { 14 int x = 0,f = 1;char ch = getchar(); 15 for

●hihocoder #1394 网络流四·最小路径覆盖

你离开我真会死。 提交于 2020-03-04 07:41:36
题链: http://hihocoder.com/problemset/problem/1394 题解: 有向图最小路径覆盖:最少的路径条数不重不漏的覆盖所有点。 注意到在任意一个最小路径覆盖的方案下, 每条路径的起点的入度为 0,终点的出度为 0,而中间的点的入度和出度以及起点的出度和终点的入度都为 1 那么把每个点拆为两个: u 和 u',分别代表其 出点 和 入点 然后对于 边 u->v, 在 u 和 v' 之间建立双向边。 那么形成二分图。 二分图匹配后,某条匹配边上的起点的出度 +1,终点的入度 +1, 那么没有被匹配到的 u'则是某条路径的起点(即没有入度), 那么没有被匹配到的 u 则是某条路径的终点(即没有出度), 正好二分图最大匹配后,没有被匹配的u'(或u)的个数是最少的,则表明路径是最少的(起点或终点是最少的)。 又因为 没有被匹配的 u'的数量 == 点数N - 匹配数 所以,有向图最小路径覆盖 =点数 -二分图最大匹配数 (更加详细的图文讲解,非常不错的 http://blog.csdn.net/tramp_1/article/details/52742572) 二分图匹配可以用匈牙利,也可以用最大流来做。 代码: #include<queue> #include<cstdio> #include<cstring> #include<iostream>

关于最大匹配,最小点覆盖,最少路径覆盖和最大独立集的总结

蹲街弑〆低调 提交于 2020-03-04 07:40:29
(1)二分图的最大匹配 匈牙利算法 (2)二分图的最小点覆盖 二分图的最小点覆盖=二分图的最大匹配 求最小点覆盖:从右边所有没有匹配过的点出发,按照增广路的“交替出现”的要求DFS。最终右边没有访问过的点和左边访问过的点组成最小点覆盖。 证明见 这里 (3)二分图的最少边覆盖 二分图的最少边覆盖=点数-二分图的最大匹配 证明: 先贪心选一组最大匹配的边放进集合,对于剩下的没有匹配的点,随便选一条与之关联的边放进集合,那么得到的集合就是最小边覆盖。 所以有:最小边覆盖=最大匹配+点数-2*最大匹配=点数-最大匹配 (4)二分图的最大独立集 二分图的最大独立集=点数-二分图的最大匹配 证明: 我们可以这样想,先把所有的点放进集合,然后删去最少的点和与之相关联的边,使得全部边都被删完,这就是最小点覆盖。所以有:最大独立集=点数-最小点覆盖 (5)有向无环图的最少不相交路径覆盖 我们把原图中的点$V$拆成两个点$Vx$和$Vy$,对于原图中的边$A->B$,我们在新图中连$Ax->By$。那么最少不相交路径覆盖=原图的点数-新图的最大匹配 证明: 一开始每个点都独立为一条路径,在二分图中连边就是将路径合并,每连一条边路径数就减一。因为路径不能相交,所以不能有公共点,这恰好就是匹配的定义。所以有:最少不相交路径覆盖=原图的点数-新图的最大匹配 友情题: bzoj1143[CTSC2008

java 判断是否为二分图 图的着色问题

别说谁变了你拦得住时间么 提交于 2020-02-28 07:12:14
判断是否为二分图 图的着色问题:把相邻顶点染成不同的颜色的问题 二分图:对图进行染色所需的最小颜色数,成为最小着色数。最小着色数为2的图称为二分图。 判断是否为二分图还是用深度优先遍历的思想。这里不需要用visited数组,给图的结点新增一个属性color,从任意结点开始,为其染色,染色的同时就相当于已经访问过了该结点,然后挨个访问这个点的邻居,为邻居染色,一旦发现某个点和他的邻居颜色一样,则不是二分图。 public class ColorTheGraph { public static void main ( String [ ] args ) { MyNode n1 = new MyNode ( 1 ) ; MyNode n2 = new MyNode ( 2 ) ; MyNode n3 = new MyNode ( 3 ) ; MyNode n4 = new MyNode ( 4 ) ; n1 . add ( n2 ) ; n1 . add ( n4 ) ; n2 . add ( n1 ) ; n2 . add ( n3 ) ; n3 . add ( n2 ) ; n3 . add ( n4 ) ; n4 . add ( n1 ) ; n4 . add ( n3 ) ; //任意顶点开始都可以 System . out . println ( dfs ( n1 , 1 )

最小割模型

别来无恙 提交于 2020-02-17 08:00:06
网络流之最小割模型: 本篇介绍了最小割的模型,如果想继续探究此模型,请阅读胡伯涛的《最小割模型在信息学竞赛中的应用》,本篇不会给与任何证明,(因为我不会。。。 首先,我们知道有一个东西叫: 最大流最小割定理 。即最大流的流值等于最小割容量。 网络流模型经典模型貌似有三个:最大权闭合子图,二分图最小点权覆盖集,二 分图最大点权独立集。 最大权闭合子图 介绍: 有一些点,每个点有点权,点权可正可负。 对于图中的任意一条有向边i和j,代表如果选择了点i就必须选择点j 你需要选择一些点使得得到权值最大。 做法: 先把答案加上所有的正权值 然后从源点向所有正权值的点连一条流量为权值的边 所有负权值的点向汇点连一条流量为权值相反数的边 原图中所有的限制关系(i,j)均建一条从i到j的流量为inf的边 最终答案减去这个图的最小割即可 例题:NOI2006 最大获利,[NOI2009]植物大战僵尸 二分图最小点权覆盖 介绍: 点覆盖集:点覆盖集是无向图 的一个点集,使得该图中所有边都至少 有一个端点在该集合内。形象地说是若干个点“覆盖”住了 与它们邻接的边,这些边恰好组成了原边集。 给出一个二分图,每个点有一个 非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 。 方法:设二分图的两个点集为A,B 从源点向A集合中的点连一条流量为对应点权的边 B集合中的点向汇点连一条流量为对应点权的边

AGC004F Namori

空扰寡人 提交于 2020-02-08 15:51:19
Link Part.1 树 众所周知树是个二分图。 因此我们可以先把树二分图染色,然后把二分图的一侧的点全部反色,那么我们可以把题目变成以下模型: 树上深度为奇数的点有一个球,每次我们可以把一个球移到它相邻的没有球的位置,然后我们要用最少的步数把所有初始的球和空位的位置全部交换。 显然有解的充要条件是初始球和空位数量相等。 对于每一条边,计算将其断开后剩下的两棵树内的球数的绝对值之差,那么这是这条边被操作次数的下界。 随便构造一下发现这个下界是可达到的。 Part.2 奇环套数 把环上的一条边 \((u,v)\) 断开,那么剩下的就是一棵树,我们对剩下的这棵树二分图染色,那么 \(u,v\) 同色。 对于树的部分还是和Part.1一样先处理,然后 \((u,v)\) 这条边进行一次操作相当于同时拿走两个点上的球或者同时在两个空位上放上球。 那么有解的充要条件就变成了球数与空位数的差值为偶数。 然后总的方案数就是这条边的操作数即总球数与总空位数的差值除以二,再加上进行这种操作之后按Part.1做的方案数。 Part.3 偶环套树 把环上的一条边 \((u,v)\) 断开,那么剩下的就是一棵树,我们对剩下的这棵树二分图染色,那么 \(u,v\) 不同色。 显然有解的充要条件是初始球和空位数量相等。 假如我们在这条边操作了 \(x\) 次(在 \(u\) 加 \(x\) 个球并在 \(v

二分图

戏子无情 提交于 2020-02-06 02:53:36
二分图,首先第一点什么是二分图: 把一个图的顶点划分为两个不相交集 U 和V ,使得每一条边都分别连接U、V中的顶点。如果存在这样的划分,则此图为一个二分图。比方说下图就是一个二分图。 ​ 那么首先第一点我们要判读一个图是否为二分图,可以采用染色的思想。对于相邻的节点然不同的颜色,然后递归在这棵树上找。我们可以申明一个color数组,int color[maxn],0代表白色,1代表黑色。对于相邻的染不同的颜色,也就是color[i]=(!color[from]);那么按照我们的定义二分图点集内不能有连线,那么如果出现起点和终点的颜色相同,那么就说明这个点集内有某条连线,也就是if(ma[from][i]&&color[from]==color[i]) return 0; int bfs() { queue<int>q; q.push(1); color[1]=1; while(!q.empty()) { int from=q.front(); q.pop(); for(int i=1;i<=n;i++) { if(color[i]==-1&&ma[from][i]) { q.push(i); color[i]=(!color[from]); } if(ma[from][i]&&color[from]==color[i]) return 0; } } return 1; }