(万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)(下)

简介: (万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)(下)

(三) 搜索和图论



树与图的存储

树是一种特殊的图,与图的存储方式相同。

对于无向图中的边ab,存储两条有向边a->b, b->a。

因此我们可以只考虑有向图的存储。

(1) 邻接矩阵:g[a][b] 存储边a->b

(2) 邻接表:

// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);

1.DFS


int dfs(int u)//模板
{
    st[u] = true; // st[u] 表示点u已经被遍历过
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j]) dfs(j);
    }
}


2.BFS


queue<int> q;//模板
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (q.size())
{
    int t = q.front();
    q.pop();
    for (int i = h[t]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true; // 表示点j已经被遍历过
            q.push(j);
        }
    }
}


3.树与图的深度优先遍历


int dfs(int u)//模板
{
    st[u] = true; // st[u] 表示点u已经被遍历过
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j]) dfs(j);
    }
}


4.树与图的广度优先遍历


queue<int> q;//模板
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (q.size())
{
    int t = q.front();
    q.pop();
    for (int i = h[t]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true; // 表示点j已经被遍历过
            q.push(j);
        }
    }
}


5.拓扑排序


bool topsort()
{
    int hh = 0, tt = -1;
    // d[i] 存储点i的入度
    for (int i = 1; i <= n; i ++ )
        if (!d[i])
            q[ ++ tt] = i;
    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (-- d[j] == 0)
                q[ ++ tt] = j;
        }
    }
    // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
    return tt == n - 1;
}


6.Dijkstra


1.朴素版dijkstra
时间复杂是 O(n^2+m), n 表示点数,m 表示边数
int g[N][N];  // 存储每条边
int dist[N];  // 存储1号点到每个点的最短距离
bool st[N];   // 存储每个点的最短路是否已经确定
// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    for (int i = 0; i < n - 1; i ++ )
    {
        int t = -1;     // 在还未确定最短路的点中,寻找距离最小的点
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        // 用t更新其他点的距离
        for (int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);
        st[t] = true;
    }
    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}
2.堆优化版dijkstra
typedef pair<int, int> PII;
int n;      // 点的数量
int h[N], w[N], e[N], ne[N], idx;       // 邻接表存储所有边
int dist[N];        // 存储所有点到1号点的距离
bool st[N];     // 存储每个点的最短距离是否已确定
// 求1号点到n号点的最短距离,如果不存在,则返回-1
int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});      // first存储距离,second存储节点编号
    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();
        int ver = t.second, distance = t.first;
        if (st[ver]) continue;
        st[ver] = true;
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > distance + w[i])
            {
                dist[j] = distance + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}


7.bellman-ford

8.spfa

9.Floyd

10.Prim

11.Kruskal

12.染色法判定二分图

13.匈牙利算法


(四)数学/数论知识



1.质数

2.约数

3.欧拉函数

4.快速幂

5.扩展欧几里得算法

6.中国剩余定理

7.高斯消元

8.求组合数

9.容斥定理

10.简单博弈论


(五)动态规划



1.背包问题

2.线性dp

3.区间dp

4.计数类dp

5.数位统计dp

6.状态压缩dp

7.树形dp

8.记忆化搜索


(六)简单版贪心



1.区间贪心类

2.Huffman树

3.排序不等式

4绝对值不等式

5.推公式


(七)C++的STL简介



1.vector, 变长数组,倍增的思想


   size()  返回元素个数

   empty()  返回是否为空

   clear()  清空

   front()/back()

   push_back()/pop_back()

   begin()/end()

   支持比较运算,按字典序


2.pair<int, int>


   first, 第一个元素

   second, 第二个元素

   支持比较运算,以first为第一关键字,以second为第二关键字(字典序)


3.string,字符串


   size()/length()  返回字符串长度

   empty()

   clear()

   substr(起始下标,(子串长度))  返回子串

   c_str()  返回字符串所在字符数组的起始地址


4.queue, 队列


   size()

   empty()

   push()  向队尾插入一个元素

   front()  返回队头元素

   back()  返回队尾元素

   pop()  弹出队头元素


5.priority_queue, 优先队列,默认是大根堆


   size()

   empty()

   push()  插入一个元素

   top()  返回堆顶元素

   pop()  弹出堆顶元素

   定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;


6.stack, 栈


   size()

   empty()

   push()  向栈顶插入一个元素

   top()  返回栈顶元素

   pop()  弹出栈顶元素


7.deque, 双端队列


   size()

   empty()

   clear()

   front()/back()

   push_back()/pop_back()

   push_front()/pop_front()

   begin()/end()


8.set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列


   size()

   empty()

   clear()

   begin()/end()

   ++, -- 返回前驱和后继,时间复杂度 O(logn)


 set/multiset


       insert()  插入一个数

       find()  查找一个数

       count()  返回某一个数的个数

      erase()

           (1) 输入是一个数x,删除所有x   O(k + logn)

           (2) 输入一个迭代器,删除这个迭代器

       lower_bound()/upper_bound()

           lower_bound(x)  返回大于等于x的最小的数的迭代器

           upper_bound(x)  返回大于x的最小的数的迭代器


 map/multimap


       insert()  插入的数是一个pair

       erase()  输入的参数是pair或者迭代器

       find()

       注意multimap不支持此操作。 时间复杂度是 O(logn)

       lower_bound()/upper_bound()


unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表

   和上面类似,增删改查的时间复杂度是 O(1)

   不支持 lower_bound()/upper_bound(), 迭代器的++,--


bitset, 圧位


   bitset<10000> s;

   ~, &, |, ^

   >>, <<

   ==, !=

   count()  返回有多少个1

   any()  判断是否至少有一个1

   none()  判断是否全为0


   set()  把所有位置成1

   set(k, v)  将第k位变成v

   reset()  把所有位变成0

   flip()  等价于~

   flip(k) 把第k位取反


相关文章
|
3月前
|
机器学习/深度学习 人工智能 算法
深度学习入门:理解神经网络与反向传播算法
【9月更文挑战第20天】本文将深入浅出地介绍深度学习中的基石—神经网络,以及背后的魔法—反向传播算法。我们将通过直观的例子和简单的数学公式,带你领略这一技术的魅力。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你打开深度学习的大门,让你对神经网络的工作原理有一个清晰的认识。
|
4月前
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
|
22天前
|
机器学习/深度学习 算法 Python
机器学习入门:理解并实现K-近邻算法
机器学习入门:理解并实现K-近邻算法
30 0
|
2月前
|
机器学习/深度学习 算法
机器学习入门(三):K近邻算法原理 | KNN算法原理
机器学习入门(三):K近邻算法原理 | KNN算法原理
|
2月前
|
机器学习/深度学习 算法 大数据
机器学习入门:梯度下降算法(下)
机器学习入门:梯度下降算法(下)
|
2月前
|
机器学习/深度学习 算法 API
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
|
2月前
|
机器学习/深度学习 算法
机器学习入门:梯度下降算法(上)
机器学习入门:梯度下降算法(上)
|
4月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
55 6
|
4月前
|
存储 算法
【C算法】编程初学者入门训练140道(1~20)
【C算法】编程初学者入门训练140道(1~20)