zoukankan      html  css  js  c++  java
  • 算是一份学习计划

    复习

    基础算法:

    文件类型和文件操作      高精度计算     数据排序     递推算法    递归算法   搜索与回溯算法    贪心算法   分治算法   广度优先搜索    动态规划

    数据结构:

    栈      队列     树     图论算法

    (复习看看书,一本通过一遍,不懂多思考,算法搜博客,瞻仰神牛思路理解)

    深入理解(参考了神牛九野的算法入门计划)

    BFS+DFS 搜索    并查集、最小生成树、递推、同余(注意知识点:树的概念、图的概念(非常重要,请自行百度))

    背包、矩阵快速幂、素数、二分查找

    专题资料推荐:背包九讲,素数表的三种打发(给出一种,另一种常有的是prime[i] = true表示i为素数)矩阵快速幂模版

    优先队列(最小堆)、状态压缩、单源最短路

    最短路建议先学习spfa算法

     

     1     int dis[N];//N个点 此处给出邻接表写法(若不熟悉可以下拉查看邻接表的示意图)  
     2     int spfa(int start, int end, int n){//最短路的起点,终点,图的下标[1,n]  
     3         for(int i = 1; i <= n; i++)dis[i] = 100000000;  
     4         dis[start] = 0;  
     5         queue<int>q; q.push(start);   
     6         while(!q.empty()){  
     7             int u = q.front(); q.pop();  
     8             for(int i = head[u]; i!=-1; i = edge[i].next){  
     9                 int v = edge[i].to;        //遍历 以u为起点的边 的终点  
    10                 if(dis[v] > dis[u]+edge[i].dis)  {  
    11                     dis[v] = dis[u]+edge[i].dis;  
    12                     q.push(v);  
    13                 }  
    14             }  
    15         }  
    16         return dis[end];  
    17     }  

    1、注意对于最短路中存在负环判定:对于spfa算法,当某个点入队列(入队列的意义就是该点被松弛了(更新))次数>n次,就说明该点在负环上(可以简单证明一个点至多被更新n次(n为图中的顶点数))。

    2、优先队列:类似于堆,出队的元素不是在队尾的元素,而是队列中最小的元素(我们有时可以在队列中存储结构体元素,只需重载运算符即可)。

    实例:

    1 struct node{
    2     int x, y;
    3     bool operator<(const node&a) const
    4     { if(a.x==x) return a.y<y;  return a.x<x; } //根据x,y值比较node结构体的大小
    5 };

    3、状态压缩:当某些状态只有true or false,时我们可以用一个整数来表示这个状态。

    示例:

    有3块不同的蛋糕编号1、2、3, 被老鼠啃过, 那么蛋糕只有2种状态, 我们用0表示没有被啃过, 1表示被啃过。

    显然我们可以得到所有状态:000、001、010、011、100、101、110、111.

    而上述二进制数对应的整数为 [0, 2^3) . (如二进制011 = 整数3表示 第2、3块蛋糕被啃过,第一块蛋糕没有被啃过)

    我们可以用 for(int i = 0; i < (1<<3); i++) 来遍历所有的状态。

    把多个事物的状态利用二进制含义压缩为一个整数称为状态压缩。

    4、利用优先队列优化最短路时, 我们可以先出队距离起点最近的点, 则若出队的为终点显然我们已经得到了一条最短路了。

    树的遍历、简单博弈、欧拉路径、Floyd算法

    对于图的储存(邻接表、邻接矩阵)

    简述下邻接表:

     1 struct Edge{  
     2     int to, next;  
     3 }edge[MAXN];//MAXN为边数  
     4 int head[N], edgenum;//N为点数  
     5 void addedge(int u, int v){  
     6     Edge E={v,head[u]};  
     7     edge[edgenum] = E;  
     8     head[u] = edgenum++;  
     9 }  
    10 void init(){ memset(head, -1, sizeof(head)); edgenum = 0; }//注意表头的初始化 

    网络流、网络流求最小割、最小割定理

    1、简述一下最小割:对于一个图,我们要删除一些边使得 1点与n点不连通。

    删边的费用为边权值,则总边权和就是 一个可行解的割边集的权值

    当费用最小时,我们称为最小割。

    最小割 = 最大流 做一个简要证明:

    我们要找一个 1点和n点的最小割 边权和(这个答案是 1点到n点的最大流)

    首先我们把1、n作为源点和汇点,跑一次网络流

    那么对于某条流, 显然说明了这条流是 连接着1点和n点的一条路径。

    这条路径我们必须去掉,当然删除这条路径上的任意一条边就可以认为去掉了这条路径。

    而这条路径上的任意边 边内的流量就是 这条路径的流量

    因此为了得到删除这条路径的最小费用,我们选择这条路径上满流的边(这样不会有多余的费用产生)

    此时删边的费用=边权值=流量

    对于每条连接着1-n的路径都这样操作, 就能得到:最大流 = 最小割

    (注意以上1点和n点只是举例,可以替换为任意两点或者任意两个点集,而非具体的定义)

    补充:对于上述所说的某条路径:路径上的边必然有一条或者多条是满流的。

    我们可以用反证法:假设所有边都是不满流的,此时我们还可以再在这条边上增加流量直到某条边满流为止。

    2、网络流的建图是重点。

    1)可以通过虚拟一个源点(汇点)来限制流入(流出)整个网络的流量

    比如:当源点为1时,我们用 0 作为源点 并建一条 0->1 边权为C的边,这样就能限制流入流量为C。

    2)当有很多个源点时,我们也可以建一个虚拟源点来连接所有源点,这样就只有1个源点了。

    3)对于某个点 i ,我们可能只允许流过C流量,则此时我们把i点拆开(就是用两个点来表示i点(比如 i 和 i+N )) 然后 i 与 i+N 中间建一条边权为C的边 来对i点限流。

    3、可先学习白书的递归版dinic,然后手敲过题。

    白书模版请点我。←边板子的水题请点我

    各类网络流模板:http://www.notonlysuccess.com/index.php/algorithm-of-network/

    完全二叉树、线段树、线段树的Lazy操作

    线段树资料:http://blog.csdn.net/metalseed/article/details/8039326

    线段树的应用-04国家队论文

    胡浩线段树题集及代码模式:http://www.notonlysuccess.com/index.php/segment-tree-complete/

    一个木有模板的专题,请多仔细阅读资料(然后刷题)

    线段树学习:

    0、04年国家队论文、白书

    1、建议学习胡浩版的线段树(即一个节点用一个结构体来表示)

    1     struct node{  
    2         int l, r;  
    3         int val;  
    4     }tree[N*4];  

    这样容易理解线段树的结构(如果不熟悉线段树的结构,可以在vs2012以上版本的编译器的单步调试中查看tree这个变量,会比较清楚地看到线段树的酷炫结构,这是帮助理解的重要一步)

    本博客的线段树也是hh牛那里学习的,较容易形成模版化减少出错。

    2、线段树的另一个重要功能:延迟操作

    比如我们对一个数组a有2种操作

      一、区间[l,r] 每个数+ val

     二、单点求值

    1 struct node{  
    2     int l, r;  
    3     int sum, lazy;  
    4 }tree[N*4]; 

    那么其实如果我们修改了1000次[1,n]区间,而在第1001次才求某点的值,那么我们不用急着把每个点更新了

    而是在[1,n]这个区间做一个标记,表示这整个区间的数都被加上了一个值,那么前1000次操作都只需要对lazy修改即可。

    等询问时再把这个lazy标记传到下面的区间去。

    这种操作就叫延迟操作
    3、线段树的延迟操作,建议写成当前区间最新,即当这个区间有lazy的标记时,这个区间也要保持最新

    2-SAT、简单博弈

    (注意知识点:对STL的set集合学习)

    set用法简介:wenku.baidu.com/view/b71a8b524431b90d6c85c746.html

    2-sat的简要在↓前面,一般可以用dfs或者tarjan缩点判断,这里暂且推荐dfs版本,较容易理解且编程复杂度不会太高。

    2-sat 白书模版

    字典树、KMP

    字典树:一个重要特色就是省内存, 多个前缀相同的字符串只需要记录一次(言外之意:对于某节点的所有子树,他们的字符串都是有公共前缀的)

    字典树资料:百度百科

    字典树模版:blog.csdn.net/acmmmm/article/details/12250267

    KMP个人简介(纯粹广告):blog.csdn.net/acmmmm/article/details/9863495

    KMP其他资料:blog.csdn.net/yaochunnian/article/details/7059486

    KMP的复杂度是线性的,即O(n+m);

    关于KMP的2个版本:普通KMP的失配数组 next[0] = 0, 滑步函数优化的失配数组 next[0] = -1;

    这里推荐先学习普通版本KMP,滑步函数据说速度稍快,但失去了KMP本身的含义,且普通KMP的速度对于比赛已经足够快了。

    有向图的强连通分量、缩点

     强连通是对有向图求环的算法,tarjan(相当于dfs)

    主要是环具有些特性,因此把环视为一个点,对图中环进行缩点,并给图重新标号

    模版性较强。

    强连通算法可参考白书319页 或 这里

    更高端的在这里:www.byvoid.com/blog/scc-tarjan/

    强连通模版

    RMQ问题、LCA转RMQ、树状数组

    RMQ问题:区间求最值,可以用线段树等解决; 

    LCA:最近公共祖先,可以用离线的tarjan,在线的LCA转RMQ(预处理O(nlogn),询问O(1),LCA倍增法(预处理O(nlogn),询问O(logn))

    模版变动不大,主要多做题。

    树状数组:对于一个数组,可以区间求和,支持单点更新,复杂度均为O(logn);

    拓展:树状数组的区间操作

    LCA题集 

    LCA倍增法模版

    LCA转RMQ解法示意

    数位dp、单调队列、滚动数组、费用流      差分约束(拓展(引用自点击打开链接))

    乘法逆元:

    (a / b)%mod  =  a * (b^(mod-2))

    b^(mod-2)套个快速幂,复杂度是log(mod), 基本是一个常数。

    ·无向图的割顶和桥、树的重心       ·无向图的双连通分量       ·无向图的双连通分量      ·拓展欧几里德、AC自动机

    ·二分匹配、基数排序

    二分匹配的图论相关:(1)(2

     二分匹配的定义:(1

    ·后缀数组       ·次小生成树、区间dp

    当520走到这里时,再往前看,看以前的题和以前的自己,一定会惊讶自己走了这么远~



     

     

     

    PS
  • 相关阅读:
    MySQL经典面试题--SQL语句
    awk命令
    mysql安装配置
    notepad++使用
    Xshell使用
    说明
    对 MMO 游戏的调研
    对 VR 项目开发流程的调研
    对 Unity 动态加载资源的调研
    对 Unity 太空射击游戏的实践
  • 原文地址:https://www.cnblogs.com/five20/p/7531905.html
Copyright © 2011-2022 走看看