随笔分类 -  最大流&二分匹配

摘要:题意:给定一些学生和课程的关系,问是否每一门课程能唯一对应一个学生。解法:每一条边对应一个选择关系,问题就是求一个完备匹配是否存在。代码如下:#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;int P, N;char G[105][305], vis[305];int match[305];bool path(int u) { for (int i = 1; i 阅读全文
posted @ 2013-04-07 09:23 沐阳 阅读(263) 评论(0) 推荐(0)
摘要:以前在杭电上做过,不过代码提交到POJ就WA了,原因还是程序存在一定的bug:http://www.cnblogs.com/Lyush/archive/2012/03/28/2422060.html在处理开始状态为0状态,匹配结果不进行统计的过程中,正确的处理方式应该是忽略掉所有能够工作的0状态的所有工作,因为这样的工作肯定是先让他们在0状态工作完。然后将其他的工作进行连边,然后求一个最大顶点覆盖(所有的边都至少有一个顶点落在所求顶点集合内),也即所有的工作至少能够有一台机器进行执行。代码如下:#include <cstdlib>#include <cstring>#i 阅读全文
posted @ 2013-04-07 09:03 沐阳 阅读(240) 评论(0) 推荐(0)
摘要:题意:给定一个方格,格子中的每点由空地,草地和墙组成,每个空地可以放置一个机器人,每个机器人能够向四个方向扫射激光,所以要给定一种方案能够在棋盘上放置足够多的机器人。激光可以穿过草地但是不能够穿过墙。解法:这题其实就是经典的二分匹配构图题,做法是将行和列进行拆分,也即如果某一行中有一堵墙,那么将墙前面和后面视为不同的一行,对列进行同样的处理,那么每个空地就需要获得一个新的行和列属性,通过遍历整个图来给每一块空地分配一个行和列号。分配要尽可能的紧凑。对于任何一块空地,要占用一个行和一个列(意味着该行和该列内不能够再容下其他空地)对于每一块空地,将其所对应的行号和列号分为图两个部分,构成二分图。二 阅读全文
posted @ 2013-04-03 10:31 沐阳 阅读(341) 评论(0) 推荐(0)
摘要:题意:有K个挤奶站,C头奶牛,每个挤奶站每天最多只能够为M头奶牛服务,奶牛到奶牛,奶牛到挤奶站都有一个距离,问一天能够为所有的奶牛都挤奶的匹配方案中,选择最远的距离最小方案。解法:通过二分枚举来构建边的关系,然后用网络流求解是否所有的牛在满足条件的情况下是否都能够被挤奶。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define inf 0x3fffffffusing namespace std;int K, C, M, idx;int 阅读全文
posted @ 2012-10-17 22:46 沐阳 阅读(301) 评论(0) 推荐(0)
摘要:根据关系建一个图,然后就是后面的插座的传递闭包,一个floyd构边。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <map>#include <string>#define INF 0x3fffffff#define CN(x) (255+(x))#define MN(x) (555+(x))#define MAXN 500using namesp 阅读全文
posted @ 2012-09-20 22:21 沐阳 阅读(399) 评论(0) 推荐(0)
摘要:依据题中所给定的关系构图,直接网络流。源点到食物,食物到人,人拆成两个点,流量为1,再从人到饮料。代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#define INF 0x3fffffff#define F(x) (x)#define N(x) (205+(x))#define CPN(x) (410+(x))#define D(x) (615+(x))using namespace std;int n, f, d, head[1005] 阅读全文
posted @ 2012-09-20 09:31 沐阳 阅读(325) 评论(0) 推荐(0)
摘要:这里参看了大牛的解题思路,学习了很多。原来上下界流的求法是这么的灵活,尤其我是用的临界表存储的边,删除更新很不方便。http://www.shuizilong.com/house/archives/sgu-176-flow-construction/http://hi.baidu.com/lxc_0601/blog/item/39e4e2ecd3be0b2f62d09f95.html这里要进行说明的求解一个有上下界的网络流的步骤:1.首先进行构图,对于那么对流量没有限制的边,我们直接将容量赋值为原始的容量,而对于有流量要求的边,我们将容量减去下界并将其等价与无下界的边。最后就是添加一个附加汇点 阅读全文
posted @ 2012-07-08 14:00 沐阳 阅读(1978) 评论(1) 推荐(0)
摘要:有一条东西向流淌的河,宽为 W,河中有 N 块石头,每块石头的坐标(Xi, Yi)和最大承受人数 Ci 已知。现在有 M 个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳 D 米,每跳一次耗时 1 秒。问他们能否全部穿越这条河流,如果能,最少需要多长时间。 <= N <= 50, 0 < M <= 50, 0 <= D <= 1000, 0 < W(0<= 1000, 0 < Xi < 1000, 0 < Yi < W, 0 <= Ci <= 1000)。刚看完这题,想当然的认为它是一道最小费用流 阅读全文
posted @ 2012-07-07 16:09 沐阳 阅读(1185) 评论(0) 推荐(0)
摘要:题目意思是有一些蜥蜴在一个迷宫里面,求这些蜥蜴还有多少是无论如何都逃不出来的。题目只给定一个行数,一个最远能够跳跃的距离,列数是不确定的(题目告知列数小于等于20),但是数据一定会是一个矩阵。每只蜥蜴有一个初始的位置,题目保证这些位置都有一些柱子,每次蜥蜴从一个位置跳到另外一个位置的时候,就会由于反作用力使得一根柱子倒下。很显然,这一题,可以用网络流来求解,那么如何去构图呢?首先我们要确定一个贪心思想,即如果从某一根柱子能够直接跳到迷宫的外面,那么我们就将这个点连接到汇点,而不用将这个点连接到其他的点了。对于哪些不能跳出去但是又有柱子的点,那么我们就去按照跳跃距离搜寻有没有其他的柱子能够去.. 阅读全文
posted @ 2012-07-06 17:31 沐阳 阅读(946) 评论(0) 推荐(0)
摘要:该题是给定对个任务,然后告诉你这多个任务在两个不同的核心上执行任务所花费的不同代价,并且还告诉如果其中一些任务不在同一个核心上面运行的话,还有有多余的开销。最后问我们完成所有任务的最小开销是多少? 对于这个问题,我们先把问题简单话一下,如果没有第二个约束条件,仅仅只有在两个核上的运行时间。那么可能你会说对每个时间所花费的时间取一个最小值就可以了,事实也确实如此,但是如果用流网络来建立这个模型的话,那么我们需要将这个事件拆成两个点,从源点流向左边点的容量是一个核心上花费的时间,两个事件点之间的容量为无穷大,右边点流向汇点的容量为该事件在第二个核心上面所花费的时间,由于中间的边的容量是无穷大... 阅读全文
posted @ 2012-07-06 10:47 沐阳 阅读(460) 评论(0) 推荐(0)
摘要:题义很简单,还记得方格取数(1)的时候,使用状态压缩写的,这里由于行列数太大,因此无法进行压缩。所以要运用的最小割最大流的思想来解这道题。 大概是这样分析的,题义是要我们求在一个方格内取出N个点,使得这N个独立的(不相邻)点集的和最大。我们可以将问题转化为最小割来求解。首先,我们将方格进行黑白相间的染色,然后再将任意一种颜色(黑色)作为源点,一种颜色(白色)作为汇点。我们的算法过程就是一个不断寻找增广路的过程。当我们找到最大流的时,也就是此时不存在从黑色到白色的路径,也即不存在不相邻的两个方格能够连通了。而此时的最大流就是分割两个区间的最小割,拿总合值减去这个最小割就是我们想要得到的结果... 阅读全文
posted @ 2012-07-06 09:24 沐阳 阅读(420) 评论(0) 推荐(0)
摘要:该题题义是这样的,有N台机器安排去组装电脑,每台电脑有P个零部件,一台可以出产的电脑必须要求每个部件都有。每台机器能够接受的本成品电脑不同,对于每个部件,输入数据给出了0(一定不能够在半成品上出现),1(一定要在上面出现),2(可以出现也可以不出现)。每台机器生产出来的半成品(或者成为了成品)的情况也有不同,对于每个部件0代表经过这个机器加工后,该号不见没有,相反,1代表有。 由于每台机器的处理能力有限,所以这里要将点拆成边,点内的边赋值为产能,其他边均赋值为无穷大。对部件没有要求的机器为源点,对部件都有要求的机器为汇点。考虑好机器与机器之间的传递关系,建图后直接计算最大流,最后在遍历两... 阅读全文
posted @ 2012-07-03 12:49 沐阳 阅读(321) 评论(0) 推荐(0)
摘要:题中给出了各种点的定义,其实我们只要建立两个虚拟节点就可以了。一个是源点流到所有的p点,一个是汇点,所有的c点流过去,再求最大流就可以了。当然题中的输入数据比较恶心,这里用了字符串的处理方式来解决。 代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <queue>#define S N#define T (N+1)#define INF 0x3fffffff#define MAXN 105using namesp 阅读全文
posted @ 2012-07-03 10:20 沐阳 阅读(251) 评论(0) 推荐(0)
摘要:这题和其他的要用二分图匹配不太一样,只要是它允许有重叠的点可以利用,而寻找增广路径的方式是不允许一点重复利用的。所以这题要转换一下方式来间接求得。 首先对于所有的孤立进行搜索,顺带建立边的关系,对于孤立的节点一定要安放一个雷达的。然后对于剩下的的,根据贪心思想,让一个天线直接覆盖两个点的话是最优的策略,于是我们利用二分图匹配这个方法使得所有的匹配成功的边都安装天线。接下来我们再将所有没有覆盖到的点在适当位置安放天线(势必会有重复覆盖的点)。最后将三者的值相加即可。当然第一个结果和第三个结果是可以一起算的。 代码如下:#include <cstdlib>#include <cs 阅读全文
posted @ 2012-07-02 21:58 沐阳 阅读(712) 评论(0) 推荐(0)
摘要:该题题义为给定网格的中的点的坐标,现在要去将这些点摧毁,有一种武器能够一次摧毁一行或者是一列的所有目标,问最少用多少次该武器能够使得所有的目标消失。这题怎么转化为二分图去做呢,过程是这样的,首先对于每个目标有两种方式能够让其消失,一种是在其所在行上使用武器,一种是在其所在列上使用武器。那么对于所有的目标而言,只要在行列满足之一的地方使用武器就可以全部清除目标。于是我们可以将目标所在行列进行匹配,然后再求最小顶点覆盖就可以了。因为最小顶点覆盖就是满足一条边至少有一个顶点在这个顶点集中。代码如下:#include <cstdlib>#include <cstdio>#inc 阅读全文
posted @ 2012-07-02 16:51 沐阳 阅读(204) 评论(0) 推荐(0)
摘要:给定一个棋盘,有些点是被删除的,问在这种情况下最多能够在这个棋盘中放置多少1*2的多米诺骨牌。这题可以用二分图匹配来解决,将二维图复制出一份,将能够放置多米诺骨牌的两个相邻的点用边进行连接。如果采用邻接矩阵的话要开一个四维的数组G[x1][y1][x2][y2] 表示坐标为x1,y1 的点与x2,y2 的点之间是否放置一块多米诺骨牌。由于内存开不下,因此采用邻接表的形式来构造这些边。最后再求一个最大匹配即可。代码如下(两个代码只是邻接表的实现不同):#include <cstdlib>#include <cstring>#include <cstdio>us 阅读全文
posted @ 2012-06-13 15:41 沐阳 阅读(305) 评论(0) 推荐(0)
摘要:简单构图,构造一个S流向 S,M,L,X,T,赛事 T1,T2,T2...TN流向汇点T。代码如下:#include <cstdio>#include <cstdlib>#include <cstring>#include <queue>#define INF 0x3f3f3f3f#define MAXN 25using namespace std;int N, cap[40][40], flow[40][40], p[40], c[40], S = 0, T = 38;int hash[130], maxflow;void init(){ ma 阅读全文
posted @ 2012-04-05 16:28 沐阳 阅读(279) 评论(0) 推荐(0)
摘要:不能恋爱问题。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;int N;int G[505][505], visit[505], marry[505];struct P{ int h; char sex[5], style[105], fav[105];}p[505];int judge(int x, int y){ if (abs(p[x].h-p[y].h)>40) return 0; else if (p[x].sex[0] == p[y 阅读全文
posted @ 2012-04-05 14:32 沐阳 阅读(370) 评论(0) 推荐(0)
摘要:题目给定N个老鼠,M个洞,在规定的时间后,将有天敌来猎捉它们,每个老鼠都有一个速度,求一种躲藏的策略,使得受威胁的老鼠最少。(每个洞中只能藏一只老鼠)该题可以将老鼠到达可及洞的情况看作是一个匹配,于是该题就是求一个老鼠到洞的最大匹配。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#define MAXN 100using namespace std;int n, m, s, v;int G[MAXN+5][MAXN+5], visit[MAXN+ 阅读全文
posted @ 2012-04-05 14:04 沐阳 阅读(328) 评论(0) 推荐(0)
摘要:不会sap,邻接矩阵过。#include <cstdlib>#include <cstring>#include <cstdio> #include <queue>#define MAXN 375#define INF 0x3f3f3f3fusing namespace std;int cap[MAXN+1][MAXN+1], flow[MAXN+1][MAXN+1], N;int p[MAXN+1], c[MAXN+1];int seq[25][15], maxflow;inline void init(){ maxflow = 0; mems 阅读全文
posted @ 2012-03-31 16:01 沐阳 阅读(203) 评论(0) 推荐(0)