
ACM算法
文章平均质量分 62
power721
这个作者很懒,什么都没留下…
展开
-
常用算法设计方法
要使计算机能完成人们预定的工作,首先必须为如何完成预定的工作设计一个算法,然后再根据算法编写程序。计算机程序要对问题的每个对象和处理规则给出正确详尽的描述,其中程序的数据结构和变量用来描述问题的对象,程序结构、函数和语句用来描述问题的算法。算法数据结构是程序的两个重要方面。 算法是问题求解过程的精确描述,一个算法由有限条可完全机械地执行的、有确定结果的指令组成。指令正确地描述了要完成的任转载 2009-09-13 18:27:00 · 792 阅读 · 0 评论 -
LCA问题
最近公共祖先(Least Common Ancestors) 对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。 这里给出一个LCA的例子: 对于T= V={1,2,3,4,5} E={(1,2),(1转载 2009-09-16 20:10:00 · 735 阅读 · 0 评论 -
平衡二叉查找树
二叉查找树是一种非常有用的数据结构。经过一定扩充,它可以支持的操作有:Insert(插入)、Find(查找)、Remove(删除)、GetMax(取最大)、GetMin(取最小)、Prev(取前驱)、Next(取后继)、Rank(取某元素的序号)、Select(按照序号取该元素)。如果数据是随机的话,以上操作可以保证在O(logn)的期望时间内完成。但是比赛中显然出题者会给出一些刁钻的数据让最转载 2009-09-16 20:14:00 · 889 阅读 · 0 评论 -
求最大流的使用距离标号的最短增广路算法
求最大流有一种经典的算法,就是每次找增广路时用BFS找,保证找到的增广路是弧数最少的,也就是所谓的Edmonds-Karp算法。可以证明的是在使用最短路增广时增广过程不超过V*E次,每次BFS的时间都是O(E),所以Edmonds-Karp的时间复杂度就是O(V*E^2)。如果能让每次寻找增广路时的时间复杂度降下来,那么就能提高算法效率了,使用距离标号的最短增广路算法就是这样的。所谓距离标转载 2009-09-16 20:16:00 · 1959 阅读 · 0 评论 -
最小树形图
最小树形图就是给定一个有向图,求以某个给定顶点为根的有向生成树(也就是说沿着这N-1条有向边可以从根走到任意点),使权和最小。解决这个问题有一个O(VE)的算法,是这样的:对于除根外的每个顶点,选择一条权最小的入边。如果选出来的V-1条边不构成环,则可以证明这些边就是满足要求的答案。如果存在环,则将环中的边收缩成一个顶点。设x是环中的点,y不是环中的点,v为新的顶点,w0为上一步中x选择的转载 2009-09-16 20:20:00 · 785 阅读 · 0 评论 -
字符串匹配自动机
首先(不严谨地)定义自动机:自动机就是一堆状态的组合,给某个状态的自动机一个输入,它会按照自己的转移规则变到一个新的状态。事实上,可以把状态理解成顶点,把状态的转移理解成上面标着符号的边,在某个状态得到了某个符号的输入时,就转移到那条边指向的状态去。 先介绍单串匹配的自动机。对于M个字符的串S[1..M],一个用这个串进行模式匹配的自动机需要M+1个状态。设状态i输入ch时的转移为auto[i][转载 2009-09-16 20:22:00 · 1143 阅读 · 0 评论 -
虚二叉树
虚二叉树是处理统计问题的一种利器,它的最大优势就是编程无比简单。在需要统计的数据严格在某一范围内时,使用虚二叉树可以大大简化编程,但这也是虚二叉树的弱点,就是必须知道事先的数据范围,而且这个范围不能太大,必须能开一个相当的数组。虚二叉树一般的应用方法在每个节点处保存其左子树加上自身的节点数。在插入时,采用非常类似二分查找的实现方法,若目标节点在当前节点的左子树或自身(x=m),则++tot转载 2009-09-16 20:08:00 · 1497 阅读 · 0 评论 -
取石子游戏
(一)巴什博奕(Bash Game):只有一堆n 个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m 个。最后取光者得胜。显然,如果n=m+1,那么由于一次最多只能取m 个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r 为任意自然数,s≤m),那么先取者要拿走s 个物品,如果后取者拿走k(≤m)个,转载 2009-10-03 20:27:00 · 731 阅读 · 0 评论 -
背包九讲
DD牛的背包九讲 P01: 01背包问题 题目 有N件物品和一个容量为V的背包。第i件物品的费用是c,价值是w。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 基本思路 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 用子问题定义状态:即f[v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转转载 2009-10-06 10:29:00 · 843 阅读 · 0 评论 -
RMQ问题
RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j 主要方法及复杂度如下 1.朴素(即搜索) O(n)-O(n) online 2.线段树 O(n)-O(qlogn) online 3.ST(实质是动态规划) O(nlogn)-O(1) offline ST算法(Sparse转载 2009-09-16 20:09:00 · 848 阅读 · 0 评论 -
自顶向下伸展树
Splay Tree 是信息学竞赛中应用很广泛的一种平衡树。Splay在应用中的一个缺点是树的层次没有保证,比如说若顺序插入所有数据,树就变成了一条链。虽然说这样还是不影响均摊复杂度,但由于一般的实现的Insert、Splay等操作都要用到递归,故在特别设计的数据中可能会遇到递归栈溢出等不希望看到的现象。自顶向下伸展树可以解决这个问题,在它的实现中可以做到不存在任何递归。现简析其思路:转载 2009-09-16 20:07:00 · 1460 阅读 · 0 评论 -
动态规划与排列组合
动态规划与排列组合By 刘未鹏(pongba)C++的罗浮宫(http://blog.youkuaiyun.com/pongba)TopLanguage(http://groups.google.com/group/pongba) 像所有的新手一样,对一种算法思想的理解需要经历从肤浅(流于表面形式)到逐渐触摸到本质的过程。为什么说"逐渐"触摸到本质,是因为很多时候你并不确定一个解释是不是最转载 2009-09-16 19:59:00 · 856 阅读 · 0 评论 -
最小后缀算法
问题:给定一个字符串s[1...n],求它的所有后缀中最小的一个。(本文中字符串之“大”“小”均对字典序而言。)算法:定义v[1..n],其中v[i]=k表示s[i..i+k-1]在s的所有长度为k的字串中最小。我们求出每个v[i]最大的取值,再找到所有的v[i]中最大的一个,s[i..n]就是问题的答案。基本思想是这样的(先不设计实现时的数据结构):先将所有的1..n都保存在转载 2009-09-16 20:05:00 · 1773 阅读 · 2 评论 -
Hungary 算法
Hungary 算法(音译为“匈牙利算法”)是用来解决二分图匹配问题的利器。它的基本思想是通过DFS在二分图中找“交错轨”。但事实上,我认为掌握这个算法甚至根本不需要理解“交错轨”这个概念,它似乎和“决策树”“隐式图”类似,只是为了理解算法的本质而抽象出来的一种东西,在代码中不会出现,也不影响对代码的浅层理解和记忆。算法的核心是bool find(int v)函数,它的作用是:寻找顶点v可转载 2009-09-16 20:08:00 · 1223 阅读 · 1 评论 -
并查集
什么是并查集? 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。 并查集的主要操作: (1)查找:查找元素所在的集合即根节点 (2)合并:将两个元素所在的集合合并为一个集合 合并两个不相交集合判断两个元素是否属于同一集合 亲戚(Relations) 思路点拨 一 问题实质转载 2009-09-16 20:11:00 · 635 阅读 · 0 评论 -
收缩强连通分量
收缩有向图中的强连通分量大约是图论的线性算法中最具技巧性一种了。我们的首要目的是对于每个顶点设定一个Belong值,也就是它从属于哪个顶点所代表的强连通分量,至于重新建立图的边,不过是将所有边扫描一遍看是否在新图中出现而已,比较容易。下面是利用一遍DFS求强连通分量的方法:对于每个顶点,设立Num、Low、Used、Alive四个属性,一个Stack保存当前正在被遍历的顶点;每访问一个顶点转载 2009-09-16 20:12:00 · 663 阅读 · 0 评论 -
树状数组
树状数组是一个查询和修改复杂度都为log(n)的数据结构,假设数组a[1..n], 那么查询a[1]+...+a[n]的时间是log级别的,而且是一个在线的数据结构, 支持随时修改某个元素的值,复杂度也为log级别。 来观察这个图: 令这棵树的结点编号为C1,C2...Cn。令每个结点的值为这棵树的值的总和,那么容易发现: C1 = A1 C2转载 2009-09-16 20:13:00 · 850 阅读 · 0 评论 -
求最大流的Relabel-to-Front算法
除了用各种方法在剩余网络中不断找增广路(augmenting)的Ford-Fulkerson系的算法外,还有一种求最大流的算法被称为压入与重标记(Push-Relabel)算法。它的基本操作有:压入,作用于一条边,将边的始点的预流尽可能多的压向终点;重标记,作用于一个点,将它的高度(也就是label)设为所有邻接点的高度的最小值加一。Push-Relabel系的算法普遍要比Ford-Fulke转载 2009-09-16 20:19:00 · 1902 阅读 · 0 评论 -
求最大权二分匹配的KM算法
最大权二分匹配问题就是给二分图的每条边一个权值,选择若干不相交的边,得到的总权值最大。解决这个问题可以用KM算法。理解KM算法需要首先理解“可行顶标”的概念。可行顶标是指关于二分图两边的每个点的一个值lx[i]或ly[j],保证对于每条边w[i][j]都有lx[i]+ly[j]-w[i][j]>=0。如果所有满足lx[i]+ly[j]==w[i][j]的边组成的导出子图中存在一个完美匹配,那么转载 2009-09-16 20:20:00 · 1031 阅读 · 0 评论 -
Trie树|字典树的简介及实现
Trie,又称字典树、单词查找树,是一种树形结构,用于保存大量的字符串。它的优点是:利用字符串的公共前缀来节约存储空间。相对来说,Trie树是一种比较简单的数据结构.理解起来比较简单,正所谓简单的东西也得付出代价.故Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子右兄弟的方法建树的话,可能会好点.其基本性质可以归纳为:1. 根节点不包含字符,除根节点外每一个节点都只包含一转载 2009-10-15 11:26:00 · 882 阅读 · 0 评论 -
并查集及例题题解
如果:给出各个元素之间的联系,要求将这些元素分成几个集合,每个集合中的元素直接或间接有联系。在这类问题中主要涉及的是对集合的合并和查找,因此将这种集合称为并查集。 链表被普通用来计算并查集.表中的每个元素设两个指针:一个指向同一集合中的下一个元素;另一个指向表首元素。 链结构的并查集 采用链式存储结构,在进行集合查找时的算法复杂度仅为O(1);但合并集合时的算法复杂度却达到了O(n)。如果我转载 2009-10-16 21:12:00 · 9143 阅读 · 1 评论 -
DFS搜索讲解
深度优先搜索(DFS) 1.图的深度优先遍历的递归定义假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图转载 2009-10-29 18:55:00 · 1790 阅读 · 0 评论 -
A*路径寻找算法入门(转)
A*路径寻找算法入门来源于: GameDev.net 作 者: Patrick Lester原文URL: http://www.gamedev.net/reference/articles/article2003.asp翻 译: 孙璨 虽然A*(读作A星)算法对初学者来说是比较深奥难懂,但是一旦你找到门路了,它又会变得非常简单。网上有很多解释A*算法的文章,但是大多数是写给那些有一定基础的人看的,原创 2010-05-19 22:06:00 · 1287 阅读 · 0 评论 -
多重背包中多次背包 O(VN) 算法 (线性动规) 带参考程序
<br />其实解决多次背包问题还可以用线性动规的方法(类似NOIP2009普及组道路游戏的算法)<br />设背包容量t,物品件数n,每件物品体积m[i],价值s[i],可用次数c[i](0表示无限制)<br />用 b[j,i] 记录到容量为j的情况下物品i使用次数,f[j] 记录容量为j的情况的最优解。<br />动规的时候,将j从1到t循环一次,分别求解f[j]<br />对于每个f[j],可以从f[j-m[i]] (i=1..n)得来<br />转移方程为f[j]=max(f[j-m[i]]+s[转载 2010-08-05 22:04:00 · 1425 阅读 · 0 评论 -
多重背包中多次背包 O(VN) 算法1 (单调队列优化) 带参考程序
<br />多次背包<br />多次背包问题:给定 n 种物品和一个背包。第 i 种物品 的价值是 Wi ,其体积<br />为 Vi,数量是 Ki件,背包的容量为 C。可以任意选择装入背包中的物品,求装入背<br />包中物品的最大总价值。 <br /><br />方法一:可以把此物品拆分成Ki个只能用一次的物品,直接套用 0-1 背包问题的经典动规实现,但是效率太低了,需要寻找更高效的算法。此算法时间复杂度为O(C*∑(Ki)) <br /><br />方法二:拆分成体积和价值分别为原来1, 2 , 4转载 2010-08-10 19:07:00 · 5811 阅读 · 0 评论 -
教你通透彻底理解:BFS和DFS优先搜索算法
<br />作者:July 二零一一年一月一日<br />---------------------------------<br />本人参考:算法导论 <br />本人声明:个人原创,转载请注明出处。<br />ok,开始。<br />翻遍网上,关于此类BFS和DFS算法的文章,很多。但,都说不出个所以然来。<br />读完此文,我想,<br />你对图的广度优先搜索和深度优先搜索定会有个通通透透,彻彻底底的认识。<br />---------------------<br />咱们由BFS开始:<b转载 2011-01-12 19:16:00 · 2228 阅读 · 1 评论 -
教你从头到尾彻底理解KMP算法
<br />作者: July 、 saturnma 时间; 二零一一年一月一日<br />-----------------------<br />本文参考:数据结构(c语言版) 李云清等编著、算法导论<br />作者声明:个人July 对此24个经典算法系列,享有版权,转载请注明出处。<br />引言:<br />在文本编辑中,我们经常要在一段文本中某个特定的位置找出 某个特定的字符或模式。<br />由此,便产生了字符串的匹配问题。<br />本文由简单的字符串匹配算法开始,经Rabin-Ka转载 2011-01-12 19:14:00 · 67300 阅读 · 11 评论 -
网络流模板:最大流ISAP算法和Dinic算法
ISAP: #include#include#include#include#define N 505#define inf 999999999using namespace std;int n,m,s,t,dis[N],pre[N],gap[N],flow[N][N];struct edge{ int v,w; edge *next,*rev;原创 2011-06-21 21:58:00 · 3357 阅读 · 3 评论 -
Sudoku 数独 Dancing Links模板
推荐论文: momodi的《Dancing Links 在搜索中的应用》、Knuth的DLX论文、陈丹琦的《Dancing Links的应用》 Dancing Links是用来优化一类精确覆盖问题中的DFS过程。精确覆盖问题是指在一个01矩阵中,选出一些行使每一列有且原创 2011-08-05 11:25:16 · 3264 阅读 · 0 评论 -
Python素数筛选法
原理: 素数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。在加密应用中起重要的位置,比如广为人知的RSA算法中,就是基于大整数的因式分解难题,寻找两个超大的素数然后相乘作为密钥的。一个比较常见的求素数的办法是埃拉托斯特尼筛法(the Sieve of Eratosthenes) ,说简单一点就是画表格,然后删表格,如图所示: 从2开始依次往后面数,原创 2012-11-23 14:37:49 · 18946 阅读 · 7 评论 -
DP最大M子段和
给定n个数求这n个数划分成互不相交的m段的最大m子段和。 经典的动态规划优化的问题。设f(i, j)表示前i个数划分成j段,且包括第i个数的最大m子段和,那么有dp方程: f(i, j) = max { f(i - 1, j) + v[i], max {f(k, j - 1) + v[i]}(k = j - 1 ... i - 1) } 也就是说第i个数要么自己划到第j段,要么和前一个数转载 2010-04-11 16:12:00 · 2124 阅读 · 1 评论 -
最小生成树kruskal算法
Kruskal 算法 假设给定一个加权连通图G,G的边集合为E,顶点个数为n,要求其一棵最小生成树T。 Kruskal 算法的粗略描述: 假设T中的边和顶点均涂成红色,其余边为白色。开始时G中的边均为白色。 1)将所有顶点涂成红色; 2)在白色边中,挑选一条权最小的边,使其与红色边不形成圈,将该白色边涂红; 3)重复2)直到有n-1条红色边,这n-1条红色边便构原创 2010-03-23 09:52:00 · 1039 阅读 · 0 评论 -
广度优先搜索(BFS)的原理和应用
广度优先搜索(BFS)的原理和应用 二叉树中的层序遍历就属于一种BFS(Board First Search) 层序遍历会得到ABCDEFG的层序优先序列(BFS序列)。在层序遍历过程中,可以注意到先访问的节点的孩子节点必然先被访问(如访问了A后访问B和C,那么B的孩子结点一定在C的孩子结点前被访问――仅针对下一层的孩子而言)。据这个特性,可以用队转载 2009-10-29 18:58:00 · 4695 阅读 · 2 评论 -
回溯算法及例题
回溯算法的主要思想是每次只构造解的一个分量, 然后按照下面的方法来评估这个部分构造解。 如果一个部分构造解可以进一步构造而不会违反问题的约束, 我们就接受对解的下一个分量所做的第一个合法选择。 如果无法对下一分量进行合法的选择,就不必再剩下的任何分量再做任何选择了。 在这种情况下,该算法进行回溯,把部分构造解的最后一个分量替换为它的下一个选转载 2009-10-29 19:23:00 · 3340 阅读 · 0 评论 -
通过金矿模型介绍动态规划
对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢! ----转载 2009-11-30 20:37:00 · 1199 阅读 · 0 评论 -
单源最短路径Dijkstra算法
算法简介 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的原创 2010-02-09 11:30:00 · 1365 阅读 · 0 评论 -
最小生成树Prim算法
Prim 最小生成树是数据结构中图的一种重要应用,它的要求是从一个带权无向完全图中选择n-1条边并使这个图仍然连通(也即得到了一棵生成树),同时还要考虑使树的权最小。 为了得到最小生成树,人们设计了很多算法,最著名的有prim算法和kruskal算法。教材中介绍了prim算法,但是讲得不够详细,理解起来比较困难,为了帮助大家更好的理解这一算法,本文对书中的内容作了进一步的细化,希望能对大家原创 2010-02-09 11:25:00 · 1112 阅读 · 1 评论 -
最短路径Floyd算法-POJ1847Tram
定义 Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。 核心思路 通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。 从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(原创 2010-02-09 11:34:00 · 1484 阅读 · 0 评论 -
Bellman-Ford&SPFA算法
Dijkstra算法中要求边的权非负,如果遇到负权,则可以采用Bellman-Ford算法。 适用条件&范围 1.单源最短路径(从源点s到其它所有顶点v); 2.有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图); 3.边权可正可负(如有负权回路输出错误提示); 4.差分约束系统; 算法描述 1.对每条边进行|V|-1次Re原创 2010-02-09 11:37:00 · 1563 阅读 · 0 评论 -
Range Minimum Query and Lowest Common Ancestor
Range Minimum Query and Lowest Common Ancestor By danielpTopCoder Member Introduction Notations Range Minimum Query (RMQ) Trivial algorithms for RMQ A solution Sparse Table (ST) a转载 2010-03-13 16:30:00 · 868 阅读 · 0 评论