随笔分类 -  图论

摘要:这道题综合了两种常见的问题:字符串的接龙以及平均值的最优化问题。对于前者,我们可以采取把单词看成边,把首尾字母组合看成点的方法。例如对于单词ababc就是点”ab”向点”bc”连一条长度为5的边。这样问题的模型变得更加清晰,规模也得到减小。那么原问题就可以转化成在此图中找一个环,使得环上边权的平均值最大。对于这种问题,我们有很经典的解决方法:由于Average=(E1+E2+…..+Ek)/K所以Average*K=E1+E2+……+Ek即(E1-Average)+(E2-Average)+….+ (Ek-Average)=0另外注意到上式中的等于号可以改写为小于等于,那么我们可以二分答案An 阅读全文
posted @ 2012-07-13 17:28 Because Of You 阅读(1960) 评论(0) 推荐(1) 编辑
摘要:第一次接触这种类型的建图题,记录一下题意:在一个20*20的方格中,建造一些围墙,使得X和某些A与E和外界都不联通,建造围墙有对应的花费,而对于满足条件的A,有对应的收入。首先2^5枚举哪些A要被围住,然后就要求所需的最小费用,这就是典型的最大流最小割问题。其中X和所枚举的A同源连一条流量为inf的边,E和边界同汇连一条流量为inf的边。以上是watashi的简练题解,我等若菜一开始还没反应过来为什么建好图后的最小割就是把X和一些A与E隔开的最小代价呢?注意,选择了某条边为割边就表示方格中两个格子间的那条围墙被选择了。注意到S集合是X和A,T集合是E和边界,所以求一下最小割后s集合中的点无法到 阅读全文
posted @ 2012-07-12 23:26 Because Of You 阅读(675) 评论(0) 推荐(0) 编辑
摘要:给你一幅图,再给你Q个询问每个询问为id c即如果将id这条边的边权改为c的话,这条边是否可能是最小生成树中的一条边做法:先对原图做一次最小生成树,顺便记录一下树中点对间的最长树边是多少如果id的边权c小于两点间最长的树边,则肯定可以去掉路径上的一条边使得最小生成树总权值更小View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf = ~0u>>2;const int maxn = 1010;bool flag[m 阅读全文
posted @ 2012-07-06 21:31 Because Of You 阅读(889) 评论(0) 推荐(0) 编辑
摘要:zoj 3611同类型的题目poj 2688化简模型即可得这样的问题,一幅图给定起点 终点 ,求起点到终点最多经过几个点,如果两种方案经过的点数相同,选路径总长短的注意,这幅图最多只有12个点,所以立刻可以想到用状态压缩来做dp[i][j]表示以i为终点的路径 为j状态(经过了那些点)时的最短路径ps:在预处理最短路的时候不要将'$'算进去,就看成一个普通的可以走的格子就可以了因为可能会出现如下情况,'$'的费用会算了四次,所以还是先数一下有几个'$'然后再独立算吧View Code #include<cstdio>#include& 阅读全文
posted @ 2012-06-25 22:04 Because Of You 阅读(2051) 评论(1) 推荐(1) 编辑
摘要:ps:D题挂了,最后只有三个。。。。E题是赛后看着一群大神的代码YY的(网上找不到题解,好奇怪,肿么都没人写的)之所以这么迟是因为一直在纠结E题A:如果第一个人能放,那就放在中间的位置,然后第二个人不管放哪第一个人总有对称的放法B:水题C:简单贪心,错了一次D:给你一幅图,假如在地板上铺上无限的同样的图,判断从S出发能否走到无限远的地方只需要判断能否从一幅图的一个点走到相对位置相同的另一幅图中的那个点即可,通过取余来表示无限幅地图E:给你一棵树,然后又给你坐标图上的n个点,让你按照树的构成将坐标连接起来,即给所有的坐标点一个编号,将树种的点与坐标对应起来树中相交的边 在坐标中体现 的线段也相交 阅读全文
posted @ 2012-06-13 22:00 Because Of You 阅读(976) 评论(0) 推荐(1) 编辑
摘要:给出一棵树询问 a-b的路径长度是多少sum【i】记录节点i到根的距离长度对于每次询问,用RMQ预处理的LCA可以在线回答每个询问, ans=sum[a]+sum[b]-2*sum[LCA(a,b)];但是这个题目离线的tarjan算法在速度上上拥有巨大的优势,几乎是瞬秒的View Code #include<string.h>#include<stdio.h>#include<vector>#include<math.h>using namespace std;const int M =40100;const double inf = 1e20 阅读全文
posted @ 2012-04-25 02:01 Because Of You 阅读(2208) 评论(0) 推荐(0) 编辑
摘要:这两题有一个共同的特点,都是从矩阵的左上角走到右下角,求最大能获得的权值不过poj 3422可以走k次poj 3422每个点走过一次后,这个点的权值就置零了,相当于经过一次后以后每次经过都没有费用了,所以每个点拆点后u->u' 建两条边一条边容量为1 费用为负的点权另一条边容量为INF,费用为0另外如果一个点能到另一个点,还是老方法u'->v,容量为INF,费用为0;最后要限制总流量为k,即建一个源点向1建一条容量为k,费用为0的边 n*n*2(最后一个点的出点) 向汇点连一条容量为k费用为0的边最后求一下S、T的最小费用流即可View Code #include& 阅读全文
posted @ 2012-04-11 14:24 Because Of You 阅读(486) 评论(0) 推荐(0) 编辑
摘要:求给那些边增加容量能增加总的流量显然,不是满流的边,增加也没有用,所以要增加容量的是那些满流的边。做法 求一次最大流 判断有几条边满流且能被源点和汇点搜到View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAX=100005;const int INF=1000000000;struct{ int v,c,next;}edge[1000000];int E,head[MAX];int gap[MAX],cur[MAX];int 阅读全文
posted @ 2012-04-10 20:46 Because Of You 阅读(451) 评论(0) 推荐(0) 编辑
摘要:枚举区间建图,好像也可以用多重匹配来做,不过不是很熟新建源点向每头牛连边牛向barns连边barns向汇点连边,边权为barns的容量,其实就是一个二分图最后求最大流就好了View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAX=100005;const int INF=1000000000;struct{ int v,c,next;}edge[1000000];int E,head[MAX];int gap[MAX],cur 阅读全文
posted @ 2012-04-10 20:29 Because Of You 阅读(296) 评论(0) 推荐(0) 编辑
摘要:给一幅图,若干个操作,每个操作时连接两个点,对于每个操作之后的图判断图中还有几条割边解法先求出最初的图中有几条割边bridge在求的过程中顺便建立一个方向,相当于变成有向图,如果发现某条边不是割边,就利用并查集将两个点合并,也可以不合并,但是速度上就相差很多了最后,一个联通块中的点就只以一个点为根了还有,如果s-t是割边,就标记一下t现在要连接两个点a,b在找他们的LCA的时候如果发现某条边是割边就bridge--因为需要一层层上去,遍历到从a,b到LCA的每条边,所以这个过程就直接暴力网上找了,不知还有没有什么更好的方法View Code #include<stdio.h>#in 阅读全文
posted @ 2012-04-09 16:52 Because Of You 阅读(419) 评论(0) 推荐(0) 编辑
摘要:在某个点派出两个点去遍历所有的边,花费为边的权值,求最少的花费仔细分析后发现从哪个点出发是无所谓的如果从某个点出发要回到这个点,那么它走过的边肯定都被他遍历了两遍,画个图模拟一下就知道了但是如果不回来,则所走路径中有一条简单路径是可以只走一遍的,派出了两个点去遍历,也就是说有两条简单路径是可以直走一边的,我们要使这两条简单路径的总和尽可能的长,就转换为了树的最长路径问题了所以答案就为总的边权和的两倍减去树的最长路View Code #include<cstdio>#include<cstring>#include<vector>#include<que 阅读全文
posted @ 2012-04-08 11:05 Because Of You 阅读(529) 评论(0) 推荐(0) 编辑
摘要:主要是利用了反证法:假设 s-t这条路径为树的直径,或者称为树上的最长路现有结论,从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜就可以找出树的最长路证明:1 设u为s-t路径上的一点,结论显然成立,否则设搜到的最远点为T则dis(u,T) >dis(u,s) 且 dis(u,T)>dis(u,t) 则最长路不是s-t了,与假设矛盾2 设u不为s-t路径上的点 首先明确,假如u走到了s-t路径上的一点,那么接下来的路径肯定都在s-t上了,而且终点为s或t,在1中已经证明过了 所以现在又有两种情况了: 1:u.. 阅读全文
posted @ 2012-04-08 11:02 Because Of You 阅读(12348) 评论(2) 推荐(4) 编辑
摘要:找出若干个环覆盖所有的点,使得总的花费最小因为每个点只能经过一次,所以很快就可想到拆点求最小费用流建图:S->i 费用为0 流量为1i+n->T同上若有边u->vu->v+n 费用为边权,容量为1最后套套模板求一次最小费用流,如果流量等于n,表示每个点都遍历了一次,输出最小费用即可View Code #include <iostream>#include <algorithm>#include <string>#include <stdio.h>#include <string.h>#include <s 阅读全文
posted @ 2012-03-26 11:20 Because Of You 阅读(861) 评论(0) 推荐(0) 编辑
摘要:题意:某个冰块上有a只企鹅,总共可以跳出去b只,问是否可能所有的企鹅都跳到某一块冰块上,输出所有的可能的冰块的编号。由于每个点只能跳出去m只企鹅,所以要拆点假如不拆点,一个点到另一个点可能会跳多于m只企鹅通过拆点后u->u'间的容量来完成题目的要求(对点的一些限制)建图:i->i+n 容量为m i+n->j容量为INF新建源点s,s->i的容量为i点企鹅的个数然后枚举汇点求最大流就可以判断某个点是否符合条件View Code #include<stdio.h>#include<cmath>#include<string.h># 阅读全文
posted @ 2012-03-24 01:22 Because Of You 阅读(729) 评论(0) 推荐(0) 编辑
摘要:给你一幅图,对于图中的每一条边,判断1、存在于任何一颗最小生成树中 any2、至少存在于某一颗最小生成树中 at least one3、不存在任何一棵最小生成树中 none看见就想一做的图论题思路:至少存在于某一颗最小生成树中 这种情况只可能存在于相同权值的边中,所以每次对于同一权值的边一起处理,再用 最小生成树中克鲁斯卡尔的方法来搞利用并查集:如果某时刻一条边的两个端点在同一集合,如果添加这一条边,就会形成一个环,而环中其他的边都是在上一轮已经添加进去了的(权值都比当前边小)所以当前边是none(一开始初始化为none),如果不在同一集合,标记为at least one,对两个集合建边,建完 阅读全文
posted @ 2012-03-23 16:02 Because Of You 阅读(517) 评论(0) 推荐(0) 编辑
摘要:http://codeforces.com/problemset/problem/118/E给定一幅连通的无向图,输入n、m以及m条边要求给每条边一个方向,即把无向图转换成有向图,然后输出每条边(a b 表示a指向b)要求转换后的图两两间依然可以互相到达。如果不可能,输出0;方法:如果原图中存在割边,输出0;反之,随便从某个点开始dfs,把搜到的边一次输出来就好了因为没有桥,则原图是一个双连通分量,两两间可以互相搜到View Code #include<cstdio>#include<vector>#include<set>#include<cstri 阅读全文
posted @ 2012-03-23 15:44 Because Of You 阅读(439) 评论(0) 推荐(0) 编辑
摘要:最大权闭合图的证明:http://www.cnblogs.com/wuyiqi/archive/2012/03/12/2391960.html结论:正的权值的和-建图后的最小割的容量选择了一条边就会选择两个点,边的花费为正,点的花费为负,把边看成点,这个点向两个端点连一条边,表示选择这条边就会选择这两个点然后题目就相当于最大权闭合图的模型了题意:有n个点,m个选择,建造n个点各自需要一定花费,每个选择有一定的获利,会选择两个点,当然也要花费求最大的获利每个选择看成是获利点,每个点看成是花费点,新建源点向获利点建边,权值为获利的大小,花费点向汇点建边,权值为花费的大小每个选择向相应的两个点连一条 阅读全文
posted @ 2012-03-23 14:35 Because Of You 阅读(678) 评论(0) 推荐(0) 编辑
摘要:先判断有无可行流,再求最大流http://blog.csdn.net/fp_hzq/article/details/6772320在上一题上下界流中,我们已经知道了怎么判断无源汇上下界网络流有无可行流把每一天看成一个点,每个女孩也看成一个点,增加源和汇s、t,源向每一天连上[0,d]的边,每一天与每个女孩如果有拍照任务的话连上[l,r]的边,每个女孩与汇连上[g,oo]的边,于是构成一个有上下界的图所以这道题目我们可以转换一下只要连一条T → S的边,流量为无穷,没有下界,那么原图就得到一个无源汇的循环流图。接下来的事情一样:原图中的边的流量设成自由流量ci – bi。新建源点SS汇点TT,求 阅读全文
posted @ 2012-03-15 19:41 Because Of You 阅读(1241) 评论(0) 推荐(0) 编辑
摘要:这道题目算是让我学到了不少建图的细节题目保证从s到t有T条无相同道路的路径,即每条边只能用一次,每个点可以多次经过然后要求所有的路径中最大的边的最小值每条边只能用一次,可以联想到网络流,边容量为1求最小的最大可以用二分判断二分的值是否满足条件:s、t的最大流是否>=T讲一下建图的细节双向建图,即满足条件的每条边的容量都为1,可以双向流而对于zoj 3583,每个点只能经过一次(每条边当然也只能经过一次),而且是无向图,所以也需要双向流,但是由于一个点只能经过一次,就需要拆点了,拆点后再求最大流就能保证最大的流只经过每个点最多一次。View Code #include<stdio.h 阅读全文
posted @ 2012-03-14 23:08 Because Of You 阅读(713) 评论(0) 推荐(0) 编辑
摘要:对于每个点有两个数in[i],out[i],表示拆掉i的所有入边的代价和拆掉所有出边的代价对于一条边(u,v)有两种操作可以将其拆掉,要么拆除u的所有出边,要么拆除v的所有入边,两个操作至少要有一个被执行这就相当于最小点权覆盖(可以参考那篇最小割的论文)中的一条边中的任意一个点都可以覆盖这条边所以,一个操作看做一个点,一条边相当于连接两个操作的边,一个最小点权覆盖的模型就建立好了建图过程如下:新建源点汇点s、t对于每个点u,拆成u u+ns->u 容量为out【u】;u+n->t容量为in[u]对于每条边u->vu->v+n,容量为无穷大求最小割,可得最小代价,(画个简 阅读全文
posted @ 2012-03-13 11:23 Because Of You 阅读(1117) 评论(0) 推荐(0) 编辑