最短路算法

文章目录



最短路总览

最短路


朴素Dijkstra - 稠密图 - O ( n 2 ) O(n^2) O(n2)

具体思路

  • 我们需要三个数组,分别是记录边的g[][]、记录到 1 1 1 节点距离的dist[]、还有标记节点是否已经求得最短路的st[]
  • 将距离数组初始化为 I N F INF INF ,然后添加第一个最短距离:dist[1] = 0,意思就是 1 1 1 节点到 1 1 1 节点的最短距离是 0 0 0
  • 寻找没有确定最短距离的节点中距离最短的那个点
    • 将这个点的距离标记为已经求得最短距离了(因为是所有未确定中最小的)
    • 用这个点的所有边去更新其连接的其他节点
  • 重复上一步,一轮能确定一个点的最短路,重复 n n n 轮就能将所有点的最短路找到
  • 当然也可以在中间加个优化:如果第 n n n 个点的最短路已经确定,那就直接退出返回即可

时间复杂度分析

重复 n n n 轮,每轮遍历所有节点找最小值,然后遍历所有边,所以是 O ( n ∗ ( n + n ) ) O(n * (n + n)) O(n(n+n)),也就是 O ( n 2 ) O(n^2) O(n2)


使用场景

  • 稠密图尽量使用朴素 D i j k s t r a Dijkstra Dijkstra
    • 稠密图: m ≈ n 2 m ≈ n^2 mn2
    • 稠密图用邻接矩阵
  • 因为时间复杂度: O ( n 2 ) < O ( n 2 ⋅ l o g n ) O(n^2) < O(n^2·logn) O(n2)<O(n2logn) ,朴素比堆优化快

AcWing 849. Dijkstra求最短路 I

题目链接:https://www.acwing.com/activity/content/problem/content/918/

Dijkstra1

CODE
#include <iostream>     // 用于输入和输出
#include <cstring>      // 用于处理字符串
#include <algorithm>    // 用于算法操作

using namespace std;

const int N = 520;      // 定义常量N
int n, m;               // 定义整型变量n和m
int g[N][N];            // 定义二维数组g
int dist[N];            // 定义一维数组dist
bool st[N];             // 定义布尔数组st

int dijkstra(){         // 定义dijkstra函数
    memset(dist, 0x3f, sizeof dist);  // 初始化dist数组
    dist[1] = 0;        // 设置dist数组的第一个元素为0

    for(int i = 1; i <= n; ++i){  // 遍历n个节点
        int t = -1;
        for(int j = 1; j <= n; ++j)  // 寻找未被访问的距离最小的节点
            if(!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;

        st[t] = true;   // 标记节点t已被访问

        for(int j = 1; j <= n; ++j)  // 更新所有节点到源点的距离
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }

    // 如果dist[n]的值未改变,返回-1,否则返回dist[n]
    return dist[n] == 0x3f3f3f3f ? -1 : dist[n];
}

int main()  // 主函数
{
    cin >> n >> m;  // 输入n和m
    memset(g, 0x3f, sizeof g);  // 初始化g数组

    int a, b, c;
    while (m -- ){  // 输入m条边
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = min(g[a][b], c);  // 更新边的权值
    }

    int t = dijkstra();  // 调用dijkstra函数

    cout << t << endl;  // 输出结果
}



堆优化 D i j k s t r a Dijkstra Dijkstra 算法 - 稀疏图 - O ( m l o g n ) O(mlogn) O(mlogn)

我们可以发现,朴素 D j i k s t r a Djikstra Djikstra 一共分为三步:

  • 遍历所有节点
    • 找出最小路径的节点
    • 由这个节点更新其他节点的距离

其中最后两步:找出最小和更新距离可以用我们学过的一个数据结构 - 来优化


具体思路和时间复杂度分析

  • 其他地方不变,将更新过的节点用堆来储存,这样就可以将查询时间从 O ( n ) O(n) O(n) 降到 O ( 1 ) O(1) O(1),也就是说不用再遍历数组了
  • 每次弹出一个元素对其他值进行修改,复杂度就是 O ( m ⋅ l o g n ) O(m · logn) O(mlogn)
    • 这个地方其实分手写堆还是 S T L STL STL
      • 手写堆:我们自己能保证堆中只有 n n n 个元素,弹出后修改某一元素的值。那么弹出元素全部修改一遍需要 O ( l o g n ) O(logn) O(logn) ,而排空堆一共需要 m m m 次,所以一共是 O ( m ⋅ l o g n ) O(m·logn) O(mlogn)
      • S T L STL STL:我们每次更新了一个节点的值就将这个值入堆,所以说堆中一共会有 m m m 个元素,那么等全部循环完就是 O ( m ⋅ l o g m ) O(m·logm) O(mlogm)
    • 在最坏情况的稠密图中, S T L STL STL 堆复杂度是 O ( m ⋅ l o g m ) O(m·logm) O(mlogm) ,也就是 O ( n 2 ⋅ l o g ( n 2 ) ) O(n^2·log(n^2)) O(n2log(n2)) ,化简得 O ( 2 n 2 ⋅ l o g n ) O(2n^2·logn) O(2n2logn) ,这个复杂度跟手写堆的 O ( n 2 ⋅ l o g n ) O(n^2·logn) O(n2logn) 差不多,所以我们用优先队列
  • 结论就是,复杂度为: O ( m ⋅ l o g n ) O(m·logn) O(mlogn)

使用场景

  • 适用于稀疏图
    • 稀疏图: m ≈ n m ≈ n mn
    • 稀疏图用邻接表存
  • 因为时间复杂度 O ( m l o g n ) O(mlogn) O(mlogn) 比朴素版 O ( n 2 ) O(n^2) O(n2) 低:

AcWing 850. Dijkstra求最短路 II

题目链接:https://www.acwing.com/activity/content/problem/content/919/

Dijkstra2

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> pii;

const int N = 1e6 + 10;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];
int n, m;
int a, b, c;

void add(int a, int b, int c){
    e[idx] = b;
    ne[idx] = h[a];
    w[idx] = c;
    h[a] = idx++;
}

int dijkstra(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    priority_queue<pii, vector<pii>, greater<pii>> heap;
    heap.push({0, 1});
    
    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] > dist[ver] + w[i]){
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    
    return dist[n] == 0x3f3f3f3f ? -1 : dist[n];
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    
    while (m -- ){
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    cout << dijkstra() << endl;
}


D i j k s t r a Dijkstra Dijkstra 算法的局限

  • D i j k s t r a Dijkstra Dijkstra 算法没办法处理负权图,为什么呢?
    1
    Dijkstra缺陷

    • 素材来自:https://www.acwing.com/solution/content/6320/ 的评论区
      什么?原来是评论区大神(ΩДΩ)!!!orz %%%%%%
  • 总结来说,就是 D i j k s t r a Dijkstra Dijkstra 算法采用了贪心思想,所以出错,原因如下:

    • 每次取最小的值为基准,更新其他值,然后这个点被打上标记,不能在用来更新其他值,但是它的值可以被更新。
    • 如果说存在负权边,那么我之前打上标记的节点的值可能就不是最短路的值了,虽然这个点的dist[]值可以被更新,但是要想再用正确的最短路的值更新其他节点就做不到了(因为被打上标记了),所以最后的答案是可能是错的。
  • 它们一刻也没有为 D i j k s t r a Dijkstra Dijkstra 算法而哀悼,立刻赶来战场的是 — B e l l m a n _ f o r d Bellman\_ford Bellman_ford 算法和 S P F A SPFA SPFA 算法!!!



Bellman - Ford 算法 - 随便存边 - O ( n m ) O(nm) O(nm)

具体思路

bellmanford

  • 首先,循环 k k k 次(题目指定最大次数,没指定就是节点数):
    • 每次循环遍历所有边,更新可以更新的边,俗称松弛操作
  • 其次,没有了,就这么多,是的,就这么多。
  • 所有操作做完之后可以保证公式: d i s t [ b ] ≤ d i s t [ a ] + w dist[b] ≤ dist[a] + w dist[b]dist[a]+w俗称三角不等式
    • 为什么强调 B e l l m a n − f o r d Bellman-ford Bellmanford 满足这个公式呢?
      因为 D i j k s t r a Dijkstra Dijkstra 并不满足(有负权边),之前说过 D i j k s t r a Dijkstra Dijkstra 的缺陷,这就导致了如果存在负权边时,有些节点的值并不是真正的最短路,也就不满足以上公式了。
  • 由于满足这个公式,所以以上操作做完,求得的所有点的值都是 k k k 次操作内的最短路了。

时间复杂度分析

两遍循环,一重循环循环 n n n 次,每次循环都遍历每条边,把能更新的都更新一遍,那么就是 O ( n m ) O(nm) O(nm)


使用场景

  • 有负权的图
    • 但是不能有负环,有负环的话就会在负环上无线绕,得到的最短路就是负无穷-INF
  • 对操作数有限制的题
    • 有些题目会对走的次数限制在 k k k 次,那么我们就在外围循环循环 k k k 次而不是 n n n 次。
      也就是最多不经过 k k k 条边的意思。
    • 如果没有限制,那就循环 n n n 次,把所有点都轮一遍。但是一般情况下都会用之后说的 S P F A SPFA SPFA 算法。
  • 带负环的图其实也可以做,当我们进行完所有松弛操作后,所有节点的值都满足三角不等式,这个时候我们再进行一次松弛操作,如果检测出来还有能操作的点,那么一定存在负环。
    • y总说的是:走了 n n n 次,那么就一定有 n + 1 n + 1 n+1 个节点,而我们一共也就 n n n 个点,由抽屉原理得一定存在负环。
      这里应该说的是证明,但是判负环基本不用 B e l l m a n − f o r d Bellman-ford Bellmanford 来做,而是用 S P F A SPFA SPFA 算法。
    • 本题的边可以用任意方式存,只要能被遍历到即可,所以直接拿结构体数组存了。


AcWing 853. 有边数限制的最短路

题目链接:https://www.acwing.com/activity/content/problem/content/922/。

bellmanford题目

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;

const int N = 510, M = 10010;

struct{
    int a, b, c;
}edges[M];

int n, m, k;
int a, b, c;
int dist[N], backup[N];

void bellman_ford(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    for(int i = 0; i < k; ++i){
        memcpy(backup, dist, sizeof dist);
        for(int j = 0; j < m; ++j){
            auto e = edges[j];
            dist[e.b] = min(dist[e.b], backup[e.a] == INF ? INF : backup[e.a] + e.c);
        }
    }
}

int main()
{
    cin >> n >> m >> k;
    for(int i = 0; i < m; ++i){
        scanf("%d%d%d", &a, &b, &c);
        edges[i] = {a, b, c};
    }
    
    bellman_ford();
    
    if(dist[n] == INF) puts("impossible");
    else printf("%d\n", dist[n]);
}
代码疑问点解析
  • backup[]数组:
    • 备份数组,用于备份上一次更新时所有最短路的值。
    • 为什么要备份?
      • 在一次外重循环中,会对所有的边进行遍历,把能更新的更新了,但是这样就会有个问题,我先更新的值可能会对后面的更新产生影响。
        比如有一条路 A − B − C A - B - C ABC , A A A 有最短路,而 B , C B, C B,C I N F INF INF ,没有最短路,题目给定只许进行一次操作。很显然,只走一步的话 C C C 是不可能有最短路的,但是错误发生了:先遍历 A − B A - B AB 边, B B B 获得最短路,那么到这应该结束了,但是循环内会把所有边都遍历一遍,如果没有备份数组,那么 C C C 就会由 B B B 而获得最短路。
        我们一次外层循环想得到的结果是根据已经有最短路的节点去更新没有最短路的节点,而且仅仅只走一步,当没有备份时,我们可能会向外发散很多步
  •   dist[e.b] = min(dist[e.b], backup[e.a] == INF ? INF : backup[e.a] + e.c);
    
    • 这步操作的意思是:
      • 如果有一条边 A − B A - B AB ,边权为负数,比方说为 − s -s s,且两个都没最短路,那么更新的时候只用min()函数比较更新前后的值的时候就会把 B B B 的最短路更新为 I N F − s INF - s INFs ,但是其实 B B B 依然没有最短路,对于终点情况也是一样。
      • 如果只写一个裸的min()函数,不进行判断的话,需要在最后判断是否有最短路的时候把判断改为
        if (dist[n] > 0x3f3f3f3f / 2) puts("impossible");
        
        只要大于一个不可能的数就判断为没有最短路。


S P F A SPFA SPFA 算法 - 一般 O ( n ) O(n) O(n),最坏 O ( n m ) O(nm) O(nm)

有两个应用

  • 求最短路
  • 判负环

具体思路 - 求最短路

B e l l m a n − f o r d Bellman-ford Bellmanford 算法优化一下,每次不将所有边都遍历一遍,而是将更新后的节点入队,每次从队列里面拿节点进行更新。


时间复杂度分析

  • 从第一个节点开始入队,最好的情况就是每个节点只需要更新一次,那么就是 O ( n ) O(n) O(n)
  • 最坏的情况是:
    spfa

AcWing 851. spfa求最短路

题目链接:https://www.acwing.com/activity/content/problem/content/920/。

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f

using namespace std;

const int N = 1e5 + 10;
int h[N], e[N], ne[N], w[N], idx;
int n, m;
int a, b, c;
bool st[N];
int dist[N];

void add(int a, int b, int c){
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

int spfa(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    queue<int> q;
    q.push(1);
    st[1] = true;
    
    while(q.size()){
        auto t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            
            if(dist[j] > dist[t] + w[i]){       // 这一步判断必须加上,防止无限入队导致TLE
                dist[j] = dist[t] + w[i];
                if(!st[j]){
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    
    return dist[n];
}

int main()
{
    memset(h, -1, sizeof h);
    
    cin >> n >> m;
    
    while (m -- ){
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    int ans = spfa();
    
    if(ans == INF) puts("impossible");
    else printf("%d\n", ans);
}
代码细节
  • st[]数组:用来标记队列中的节点,已经入队了就没必要再次入队了,防止无限入队。
  • if判断是否更新而不是直接用min()函数:防止无限入队。

具体思路 - 判负环

维护一个cnt[]数组,每当某节点被更新一次就在源点对应的记录数组cnt[]+1,当某个记录数突破了节点数时,肯定存在负环,证明详情见 B e l l m a n − f o r d Bellman-ford Bellmanford 算法y总原话之抽屉原理


AcWing 852. spfa判断负环

题目链接:https://www.acwing.com/activity/content/problem/content/921/。

spfa判负环

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 2010, M = 10010;
int n, m;
int a, b, c;
int h[N], e[M], ne[M], w[M], idx;
int dist[N], cnt[N];
bool st[N];

void add(int a, int b, int c){
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

bool spfa(){
    //memset(dist, 0x3f, sizeof dist);	加不加都行
    //dist[1] = 0;
    
    queue<int> q;
    for(int i  = 1; i <= n; ++i){
        q.push(i);
        st[i] = true;
    }
    
    while(q.size()){
        int t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            
            if(dist[j] > dist[t] + w[i]){
                dist[j] = dist[t] + w[i];
                cnt[j] = cnt[t] + 1;
                
                if(!st[j]){
                    q.push(j);
                    st[j] = true;
                }
                
                if(cnt[j] >= n) return true;
            }
        }
    }
    
    return false;
}

int main()
{
    memset(h, -1, sizeof h);
    
    cin >> n >> m;
    while (m -- ){
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    if(spfa()) puts("Yes");
    else puts("No");
}
代码疑点解读
  • 为什么一开始把所有点入队:
    • 因为这样可以检测到所有边上的负环,而不是仅仅只有最短路上的负环了。
      全部入队
      素材来自:https://www.acwing.com/solution/content/6336/评论区。
      什么?又是评论区大神?(ΩДΩ) orz %%%%%
  • 为什么dist[]不用初始化:
    • 因为如果边权为正数,dist[]永远不会更新,直到遇见了负数才会更新,如果有负环那就会一直更新直到爆 n n n 返回false


F l o y d Floyd Floyd 算法 - O ( n 3 ) O(n^3) O(n3)

思路简介

采用了动态规划思想,具体怎样我也不知道 >_<,没学过呜呜呜。
总之很短很暴力。
别问,问就是背过

菜就多练,学不会就背过。
暴力是暴力, F l o y d Floyd Floyd F l o y d Floyd Floyd
你要是一直拿 F l o y d Floyd Floyd 当暴力。
你咋不去自己写一个?


时间复杂度分析

三重循环所以是—— O ( n 3 ) O(n^3) O(n3)
太美丽了家人们。


AcWing 854. Floyd求最短路

题目链接:https://www.acwing.com/activity/content/problem/content/923/。

floyd

#include <iostream>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;

int n, m, k;
const int N = 210, M = 20010;
int d[N][N];

void floyd(){
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                d[i][j] = min(d[i][j], 
                	(d[i][k] == INF || d[k][j] == INF) ? INF : d[i][k] + d[k][j]);
                
                // y总写的d[i][j] = min(d[i][j], d[i][k] + d[k][j]);              
}

int main()
{
    cin >> n >> m >> k;
    
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            if(i == j) d[i][j] = 0;
            else d[i][j] = INF;
            
    while (m -- ){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        d[a][b] = min(d[a][b], c);
    }
    
    floyd();
    
    while(k--){
        int a, b;
        scanf("%d%d", &a, &b);
        
        if(d[a][b] == INF) puts("impossible");
        else printf("%d\n", d[a][b]);
    }
}
代码疑点解读
  • 为什么跟y总不一样的地方能过,什么思路?
    • 这个跟 B e l l m a n − f o r d Bellman-ford Bellmanford 一样,把所有边轮了一遍,所以会出现之前说的INF - k的情况出现,所以加了个判断。
    • 至于为什么这么写,我只能说我是仿照 B e l l m a n − f o r d Bellman-ford Bellmanford 写的判断,但是只判断前一个或后一个都会 WA,但是一起判断了就AC了,所以我就这么写了,原理我也不懂,嘿嘿。
  • 为什么初始化的时候把每个自己到自己的节点距离设为 0 0 0
    源点初始化
    • 素材来源:https://www.acwing.com/activity/content/code/content/48531/评论区。
      什么?又双叒叕是评论区大神???!!!(ΩДΩ) orz %%%%

写了一天总算写完了,真的很复杂啊 %%%%%%%%%%%%%%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/208168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HuggingFace Transformer库学习笔记】基础组件学习:Tokenizer

基础组件——Tokenizer &#xff08;1&#xff09;模型加载 from transformers import AutoTokenizersen "弱小的我也有大梦想!" # 从HuggingFace加载&#xff0c;输入模型名称&#xff0c;即可加载对于的分词器 tokenizer AutoTokenizer.from_pretrained("m…

存储虚拟化的写入过程

存储虚拟化的场景下&#xff0c;整个写入的过程。 在虚拟机里面&#xff0c;应用层调用 write 系统调用写入文件。write 系统调用进入虚拟机里面的内核&#xff0c;经过 VFS&#xff0c;通用块设备层&#xff0c;I/O 调度层&#xff0c;到达块设备驱动。虚拟机里面的块设备驱动…

助力android面试2024【面试题合集】

转眼间&#xff0c;2023年快过完了。今年作为口罩开放的第一年大家的日子都过的十分艰难&#xff0c;那么想必找工作也不好找&#xff0c;在我们android开发这一行业非常的卷&#xff0c;在各行各业中尤为突出。android虽然不好过&#xff0c;但不能不吃饭吧。卷归卷但是还得干…

网站实现验证码功能

一、验证码 一般来说&#xff0c;网站在登录的时候会生成一个验证码来验证是否是人类还是爬虫&#xff0c;还有一个好处是防止恶意人士对密码进行爆破。 二、流程图 三、详细说明 3.1 后端生成验证码 Override public Result<Map<String, String>> getVerifica…

用element-ui进行简单的商品管理

安装element-ui 项目的控制台输入npm i element-ui -S main.js import ElementUI from element-ui;//引入element-ui模块 import element-ui/lib/theme-chalk/index.css;//引入element-ui的css样式 Vue.use(ElementUI);//使用ElementUI 商品管理组件 <template><…

STM32CubeMx+MATLAB Simulink点灯程序

STM32CubeMxMATLAB点灯程序 ✨要想实现在MATLAB Simulink环境下使用STM32&#xff0c;前提是已经搭建好MATLAB环境并且安装了必要的Simulink插件&#xff0c;以及对应的STM32支持包。 &#x1f33f;需要准备一块所安装支持包支持的STM32开发板. &#x1f516;具体支持包详情页…

Java基础第十八天 - 网络编程

计算机网络 什么是计算机网络 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统&#xff0c;从而使众多的计算机可以方便地互相传递信息&#xff0c;共享硬件、软件、数据信息等资源。 计算机网络主要功能 1.实现资源共享 2.信息…

【VMware相关】VMware vSphere存储方案

一、iSCSI存储 参考文档 VMware官方文档&#xff1a;配置iSCSI适配器和存储 华为配置指南&#xff1a;VMware ESXi下的主机连通性指南 1、配置说明 如下图所示&#xff0c;VMware配置iSCSI存储&#xff0c;需要将物理网卡绑定到VMKernel适配器上&#xff0c;之后再将VMKernel适…

微信开发者工具真机调试连接状态在正常和未连接之间反复横跳

开启局域网模式能解决这个问题&#xff0c;目前只找到这一个方法

测试新人如何去开展软件测试工作

1. 软件测试 在一般的项目中&#xff0c;一开始均为手动测试&#xff0c;由于自动化测试前期投入较大&#xff0c;一般要软件项目达到一定的规模&#xff0c;更新频次和质量均有一定要求时才会上自动化测试或软件测试。 1.1. 项目中每个成员的测试职责 软件测试从来不是某一个职…

微信小程序自定义顶部导航栏的胶囊和微信自带的胶囊一样的透明背景色

想要实现微信自带的右上角胶囊背景透明很简单&#xff0c;只需要在pages.js里面设置下面配置就可以了&#xff1a; "navigationStyle": "custom","navigationBarTextStyle": "white" 但是设置完这个后&#xff0c;胶囊的背景色是那种…

业余爱好-社会工程管理记账报税

税务问题笔记 印花税税费申报及缴纳财务和行为税合并纳税申报增值税及附加税费申报企业所得税季度A类申报残疾人就业保障金申报财务报表个税申报 印花税 印花税是对在经济活动和经济交往中书立、领受具有法律效力的凭证的行为征收的一种税。 税费申报及缴纳 财务和行为税合并…

JMeter怎样测试WebSocket

一、安装WebSocket取样器 1、从JMeter插件管理器官网下载&#xff1a; https://jmeter-plugins.org/ 搜索websocket 1、jetty-http-9.1.2.v20140210.jar 2、jetty-io-9.1.2.v20140210.jar 3、jetty-util-9.1.2.v20140210.jar 4、websocket-api-9.1.1.v20140108.jar 5、w…

DAPP开发【04】测试驱动开发

测试驱动开发(Test Driven Development)&#xff0c;是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码&#xff0c;然后只编写使测试通过的功能代码通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码&#xff0c…

SpringBoot集成邮箱验证码功能(注册/改密)

准备工作 开启SMTP服务 前往你的邮箱网站&#xff0c;以网易邮箱为例&#xff0c;打开网易邮箱地址&#xff0c;登录你的邮箱&#xff0c;进入邮箱管理后台界面。点击“设置”》》“POP3/SMTP/IMAP”后&#xff0c;点击开启SMTP服务即可。 技术实现 Spring Boot 发送邮件验证…

跨越鸿沟-颠覆性产品营销指南笔记

跨越鸿沟-颠覆性产品营销指南笔记 一、发现鸿沟 一、技术采用生命周期 技术采用生命周期 如果采用一个新产品&#xff0c;我们就得改变一贯的行为模式&#xff0c;或者改变我们依赖的其他产品或服务&#xff0c;那么&#xff0c;我们对技术采用的态度就变得很重要&#xff0c…

入门单片机和嵌入式必须学模电数电吗?

入门单片机和嵌入式必须学模电数电吗&#xff1f; 关于这个话题答案&#xff0c;不能一概而论&#xff0c;主要与从事的具体工作内容有关。 嵌入式开发&#xff0c;好多人认为硬件和软件都需要学习&#xff0c;其实不然。 嵌入式领域涵盖的内容很广&#xff0c;比如嵌入式MCU、…

【编译警告】start value has mixed support, consider using flex-start instead

css规范问题&#xff0c;flex布局下&#xff0c;justify-content:start; 应该为&#xff1a;justify-content: flex-start

深入探索Maven:优雅构建Java项目的新方式(二)

Meven高级 1&#xff0c;属性1.1 属性1.1.1 问题分析1.1.2 解决步骤步骤1:父工程中定义属性步骤2:修改依赖的version 1.2 配置文件加载属性步骤1:父工程定义属性步骤2:jdbc.properties文件中引用属性步骤3:设置maven过滤文件范围步骤4:测试是否生效 1.3 版本管理 2&#xff0c;…

【Python表白系列】无限弹窗,满屏表白代码来啦(完整代码)

文章目录 满屏表白代码环境需求完整代码详细分析系列文章 满屏表白代码 环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0&#xff08;可选&#xff0c;这个库用于打包&#xff0c;使程序没有python环境也可以运行&#xff0c;如果想发给好朋友的话需…