圖的概念、性質和存儲與簡單遍歷

前置知識:樹的基本概念及性質

為了保證學習效果,請保證已經掌握前置知識之后,再來學習本章節!如果在閱讀中遇到困難,也可以回到前面章節查閱。

學習目標

  • 掌握圖的基本概念
  • 掌握圖的一些性質

圖的概念

基本概念

圖 (Graph)?是一個二元組?𝐺=(𝑉(𝐺),𝐸(𝐺))G=(V(G),E(G))?。其中?𝑉(𝐺)V(G)?是非空集,稱為?點集 (Vertex set)?,對于?𝑉V?中的每個元素,我們稱其為?頂點 (Vertex)?或?節點 (Node)?,簡稱??;?𝐸(𝐺)E(G)?為?𝑉(𝐺)V(G)?各結點之間邊的集合,稱為?邊集 (Edge set)?。

常用?𝐺=(𝑉,𝐸)G=(V,E)?表示圖。

當?𝑉,𝐸V,E?都是有限集合時,稱?𝐺G?為?有限圖?。

當?𝑉V?或?𝐸E?是無限集合時,稱?𝐺G?為?無限圖?。

圖有多種,包括?無向圖 (Undirected graph)?,?有向圖 (Directed graph)?,?混合圖 (Mixed graph)?等

若?𝐺G?為無向圖,則?𝐸E?中的每個元素為一個無序二元組?(𝑢,𝑣)(u,v)?,稱作?無向邊 (Undirected edge)?,簡稱?邊 (Edge)?,其中?𝑢,𝑣∈𝑉u,v∈V?。設?𝑒=(𝑢,𝑣)e=(u,v)?,則?𝑢u?和?𝑣v?稱為?𝑒e?的?端點 (Endpoint)?。

若?𝐺G?為混合圖,則?𝐸E?中既有向邊,又有無向邊。

若?𝐺G?的每條邊?𝑒𝑘=(𝑢𝑘,𝑣𝑘)ek?=(uk?,vk?)?都被賦予一個數作為該邊的??,則稱?𝐺G?為?賦權圖?。如果這些權都是正實數,就稱?𝐺G?為?正權圖?。

形象地說,圖是由若干點以及連接點與點的邊構成的。

圖片

圖上的關系

點與點——鄰接

在無向圖?𝐺=(𝑉,𝐸)G=(V,E)?中,對于兩頂點?𝑢u?和?𝑣v?,若存在邊?(𝑢,𝑣)(u,v)?,則稱?𝑢u?和?𝑣v?是?相鄰(鄰接)的?。

一個頂點?𝑣∈𝑉v∈V?的?鄰域 (Neighborhood)?是所有與之相鄰的頂點所構成的集合,記作?𝑁(𝑣)N(v)?。

PS:鄰接表存儲的就是鄰域,并且由此得名。

點與邊——關聯

在無向圖?𝐺=(𝑉,𝐸)G=(V,E)?中,若點?𝑣v?是邊?𝑒e?的一個端點,則稱?𝑣v?和?𝑒e?是?關聯的

度數

與一個頂點?𝑣v?關聯的邊的條數稱作該頂點的?度 (Degree)?,記作?𝑑(𝑣)d(v)?。特別地,對于邊?(𝑣,𝑣)(v,v)?,則每條這樣的邊要對?𝑑(𝑣)d(v)?產生?22?的貢獻。

對于無向簡單圖,有?𝑑(𝑣)=∣𝑁(𝑣)∣d(v)=∣N(v)∣?。

握手定理(又稱圖論基本定理):對于任何無向圖?𝐺=(𝑉,𝐸)G=(V,E)?,有?∑𝑣∈𝑉𝑑(𝑣)=2∣𝐸∣∑v∈V?d(v)=2∣E∣?,即無向圖中結點度數的總和等于邊數的兩倍。有向圖中結點的入度之和等于出度之和等于邊數。

推論:?在任意圖中,度數為奇數的點必然有偶數個。

證明:反證法

簡單圖

自環 (Loop)?:對?𝐸E?中的邊?𝑒=(𝑢,𝑣)e=(u,v)?,若?𝑢=𝑣u=v?,則?𝑒e?被稱作一個自環。

重邊/平行邊 (Multiple edge)?:若?𝐸E?中存在兩個完全相同的元素(邊)?𝑒1,𝑒2e1?,e2??,則它們被稱作(一組)重邊。

簡單圖 (Simple graph)?:若一個圖中?沒有自環和重邊,它被稱為簡單圖。非空簡單無向圖中一定存在度相同的結點。

如果一張圖中有自環或重邊,則稱它為?多重圖 (Multigraph)?。

圖片

? 在無向圖中?(𝑢,𝑣)(u,v)?和?(𝑣,𝑢)(v,u)?算一組重邊,而在有向圖中,?𝑢→𝑣u→v?和?𝑣→𝑢v→u?不為重邊。

? 在題目中,如果沒有特殊說明,是可以存在自環和重邊的,在做題時需特殊考慮。

路徑

途徑 (Walk)?/?鏈 (Chain)?:一個點和邊的交錯序列,其中首尾是點——?𝑣0,𝑒1,𝑣1,𝑒2,𝑣2,…,𝑒𝑘,𝑣𝑘v0?,e1?,v1?,e2?,v2?,…,ek?,vk??,有時簡寫為?𝑣0→𝑣1→𝑣2→?→𝑣𝑘v0?→v1?→v2?→?→vk??。其中?𝑒𝑖ei??的兩個端點分別為?𝑣𝑖?1vi?1??和?𝑣𝑖vi??。通常來說,邊的數量?𝑘k?被稱作這條途徑的?長度?(如果邊是帶權的,長度通常指路徑上的邊權之和,題目中也可能另有定義)。(以下設?𝑤=[𝑣0,𝑒1,𝑣1,𝑒2,𝑣2,?,𝑒𝑘,𝑣𝑘]w=[v0?,e1?,v1?,e2?,v2?,?,ek?,vk?]?。)

跡 (Trail)?:對于一條途徑?𝑤w?,若?𝑒1,𝑒2,?,𝑒𝑘e1?,e2?,?,ek??兩兩互不相同,則稱?𝑤w?是一條跡。

路徑 (Path)?(又稱?簡單路徑 (Simple path)?):對于一條跡?𝑤w?,除了?𝑣0v0??和?𝑣𝑘vk??允許相同外,其余點兩兩互不相同,則稱?𝑤w?是一條路徑。

回路 (Circuit)?:對于一個跡?𝑤w?,若?𝑣0=𝑣𝑘v0?=vk??,則稱?𝑤w?是一個回路。

環/圈 (Cycle)?(又稱?簡單回路/簡單環 (Simple circuit)?):對于一條簡單路徑?𝑤w?,若?𝑣0=𝑣𝑘v0?=vk??,則稱?𝑤w?是一個環。

!!! warning
關于路徑的定義在不同地方可能有所不同,如,“路徑”可能指本文中的“途徑”,“環”可能指本文中的“回路”。如果在題目中看到類似的詞匯,且沒有“簡單路徑”/“非簡單路徑”(即本文中的“途徑”)等特殊說明,最好詢問一下具體指什么。

連通

無向圖

對于一張無向圖?𝐺=(𝑉,𝐸)G=(V,E)?,對于?𝑢,𝑣∈𝑉u,v∈V?,若存在一條途徑使得?𝑣0=𝑢,𝑣𝑘=𝑣v0?=u,vk?=v?,則稱?𝑢u?和?𝑣v?是?連通的 (Connected)?。由定義,任意一個頂點和自身連通,任意一條邊的兩個端點連通。

若無向圖?𝐺=(𝑉,𝐸)G=(V,E)?,滿足其中任意兩個頂點均連通,則稱?𝐺G?是?連通圖 (Connected graph)?,?𝐺G?的這一性質稱作?連通性 (Connectivity)?。

若?𝐻H?是?𝐺G?的一個連通子圖,且不存在?𝐹F?滿足?𝐻?𝐹?𝐺H?F?G?且?𝐹F?為連通圖,則?𝐻H?是?𝐺G?的一個?連通塊/連通分量 (Connected component)?(極大連通子圖)。

圖片

圖片

有向圖

對于一張有向圖?𝐺=(𝑉,𝐸)G=(V,E)?,對于?𝑢,𝑣∈𝑉u,v∈V?,若存在一條途徑使得?𝑣0=𝑢,𝑣𝑘=𝑣v0?=u,vk?=v?,則稱?𝑢u?可達?𝑣v?。由定義,任意一個頂點可達自身,任意一條邊的起點可達終點。(無向圖中的連通也可以視作雙向可達。)

若一張有向圖的節點兩兩互相可達,則稱這張圖是?強連通的 (Strongly connected)?。

圖片

若一張有向圖的邊替換為無向邊后可以得到一張連通圖,則稱原來這張有向圖是?弱連通的 (Weakly connected)?。

與連通分量類似,也有?弱連通分量 (Weakly connected component)?(極大弱連通子圖)和?強連通分量 (Strongly Connected component)?(極大強連通子圖)。

圖片

𝑛n?個頂點的強連通圖最多?𝑛(𝑛?1)n(n?1)?條邊,最少?𝑛n?條邊。

圖片

圖的連通性也是競賽的一個常見考點,相關算法請后面將學習,現在先理解其概念即可。

稀疏圖/稠密圖

若一張圖的邊數遠小于其點數的平方,那么它是一張?稀疏圖 (Sparse graph)?。

若一張圖的邊數接近其點數的平方,那么它是一張?稠密圖 (Dense graph)?。

這兩個概念并沒有嚴格的定義,一般用于討論?時間復雜度?為?𝑂(∣𝑉∣2)O(∣V∣2)?的算法與?𝑂(∣𝐸∣)O(∣E∣)?的算法的效率差異(在稠密圖上這兩種算法效率相當,而在稀疏圖上?𝑂(∣𝐸∣)O(∣E∣)?的算法效率明顯更高)。

特殊的圖

完全圖

若無向簡單圖?𝐺G?滿足任意不同兩點間均有邊,則稱?𝐺G?為?完全圖 (Complete graph)?,?𝑛n?階完全圖記作?𝐾𝑛Kn??。若有向圖?𝐺G?滿足任意不同兩點間都有兩條方向不同的邊,則稱?𝐺G?為?有向完全圖 (Complete digraph)?。

圖片

環圖/圈圖

若無向簡單圖?𝐺=(𝑉,𝐸)G=(V,E)?的所有邊恰好構成一個圈,則稱?𝐺G?為?環圖/圈圖 (Cycle graph)?,?𝑛n?(?𝑛≥3n≥3?) 階圈圖記作?𝐶𝑛Cn??。易知,一張圖為圈圖的充分必要條件是,它是?22?- 正則連通圖。

星圖/菊花圖

若無向簡單圖?𝐺=(𝑉,𝐸)G=(V,E)?滿足,存在一個點?𝑣v?為支配點,其余點之間沒有邊相連,則稱?𝐺G?為?星圖/菊花圖 (Star graph)?,?𝑛+1n+1?(?𝑛≥1n≥1?) 階星圖記作?𝑆𝑛Sn??。

輪圖

若無向簡單圖?𝐺=(𝑉,𝐸)G=(V,E)?滿足,存在一個點?𝑣v?為支配點,其它點之間構成一個圈,則稱?𝐺G?為?輪圖 (Wheel Graph)?,?𝑛+1n+1?(?𝑛≥3n≥3?) 階輪圖記作?𝑊𝑛Wn??。

image-20210328095407460

若無向簡單圖?𝐺=(𝑉,𝐸)G=(V,E)?的所有邊恰好構成一條簡單路徑,則稱?𝐺G?為?鏈 (Chain/Path Graph)?,?𝑛n?階的鏈記作?𝑃𝑛Pn??。易知,一條鏈由一個圈圖刪去一條邊而得。

如果一張無向連通圖不含環,則稱它是一棵?樹 (Tree)?。相關內容詳見 樹基礎 。

補圖

對于無向簡單圖?𝐺=(𝑉,𝐸)G=(V,E)?,它的?補圖 (Complement graph)?指的是這樣的一張圖:記作?𝐺ˉGˉ?,滿足?𝑉(𝐺ˉ)=𝑉(𝐺)V(Gˉ)=V(G)?,且對任意節點對?(𝑢,𝑣)(u,v)?,?(𝑢,𝑣)∈𝐸(𝐺ˉ)(u,v)∈E(Gˉ)?當且僅當?(𝑢,𝑣)?𝐸(𝐺)(u,v)∈/E(G)?。

圖片

反圖

對于有向圖?𝐺=(𝑉,𝐸)G=(V,E)?,它的?反圖 (Transpose Graph)?指的是點集不變,每條邊反向得到的圖,即:若?𝐺G?的反圖為?𝐺′=(𝑉,𝐸′)G′=(V,E′)?,則?𝐸′={(𝑣,𝑢)∣(𝑢,𝑣)∈𝐸}E′={(v,u)∣(u,v)∈E}?。

平面圖

如果一張圖可以畫在一個平面上,且沒有兩條邊在非端點處相交,那么這張圖是一張?平面圖 (Planar graph)?。一張圖的任何子圖都不是?𝐾5K5??或?𝐾3,3K3,3??是其為一張平面圖的充要條件。對于簡單連通平面圖?𝐺=(𝑉,𝐸)G=(V,E)?且?𝑉≥3V≥3?,?∣𝐸∣≤3∣𝑉∣?6∣E∣≤3∣V∣?6?。

image-20210328095019950

?

學習目標

  • 掌握圖的四種存儲方法的代碼實現
  • 理解圖的四種存儲方法各自的時間空間復雜度
  • 能夠根據題目的要求和數據范圍,選擇合適存圖方式

圖的邏輯結構

一張圖是由節點構成的,一個無向圖如下圖所示:

圖片

什么叫?「邏輯結構」?就是說為了方便研究,我們把圖?抽象?成這個樣子。

根據這個邏輯結構,我們可以認為每個節點的實現如下:

// 圖節點的邏輯結構
struct node {int data;                 // 存當前結點信息vector<int> neighbors;  // 存鄰接的所有結點
}

看到這個實現,你有沒有很熟悉?它和我們之前說的多叉樹節點幾乎完全一樣:

// 樹節點的邏輯結構
struct node {int data;                 // 存當前結點信息vector<int> son;        // 存所有的子結點
}

Copy

不過呢,上面的這種實現是「邏輯上的」,實際上我們很少用這個node類實現圖,而是用接下來介紹的幾種方法去存儲。其中包含我們前面經常提到的?鄰接表和鄰接矩陣

圖的存儲方法

接下來描述圖的具體四種存儲方式,這四種方式是我們今后和圖這種數據結構打交道的接口,請一定要掌握。

首先約定,用?𝑛n?代指圖的點數,用?𝑚m?代指圖的邊數,用?𝑑+(𝑢)d+(u)?代指點?𝑢u?的出度,即以?𝑢u?為出發點的邊數。

直接存邊

方法

使用一個數組來存邊,數組中的每個元素都包含一條邊的起點與終點(帶邊權的圖還包含邊權)。(或者使用多個數組分別存起點,終點和邊權。)

#include <iostream>
#include <vector>
using namespace std;struct Edge {int u, v, w;   // 一條邊的 起點、終點、權值
};int n, m;
vector<Edge> e;
vector<bool> vis;// 函數功能:判斷 u,v 之間有沒有邊
bool find_edge(int u, int v) {for (int i = 1; i <= m; ++i) {if (e[i].u == u && e[i].v == v) {return true;}}return false;
}// 遍歷圖
void dfs(int u) {if (vis[u]) return;vis[u] = true;for (int i = 1; i <= m; ++i) {if (e[i].u == u) {dfs(e[i].v);}}
}int main() {cin >> n >> m;// 初始化 vector 數組,也可以將 vis 定義成: “bool vis[N];” 以省去初始化。下同vis.resize(n + 1, false);e.resize(m + 1);for (int i = 1; i <= m; ++i) cin >> e[i].u >> e[i].v >> e[i].w;return 0;
}

復雜度

查詢是否存在某條邊:?𝑂(𝑚)O(m)?。

遍歷一個點的所有出邊:?𝑂(𝑚)O(m)?。

遍歷整張圖:?𝑂(𝑛𝑚)O(nm)?。

空間復雜度:?𝑂(𝑚)O(m)?。

應用

由于直接存邊的遍歷效率低下,一般不用于遍歷圖。

在 Kruskal 算法中,由于需要將邊按邊權排序,需要直接存邊。

在有的題目中,需要多次建圖(如建一遍原圖,建一遍反圖),此時既可以使用多個其它數據結構來同時存儲多張圖,也可以將邊直接存下來,需要重新建圖時利用直接存下的邊來建圖。

鄰接矩陣

方法

使用一個二維數組?g?來存邊,其中?g[u][v]?為 1 表示存在?𝑢u?到?𝑣v?的邊,為 0 表示不存在。

如果是帶邊權的圖,可以在?g[u][v]?中存儲?𝑢u?到?𝑣v?的邊的邊權,0 表示沒有連接,其他值表示權重。

如果是無向圖,則將一條無向邊拆成兩條方向相反的邊即可。(所謂的「無向」,也就等同于「雙向」)

#include <iostream>
#include <vector>
using namespace std;const int N = 1e5+5;
int n, m;
bool vis[N];
bool g[N][N];bool find_edge(int u, int v) { return g[u][v]; }void dfs(int u) {if (vis[u]) return;vis[u] = true;for (int v = 1; v <= n; ++v) {if (g[u][v]) {dfs(v);}}
}int main() {cin >> n >> m;fill_n(vis, N, false);  // 將 vis 數組清 false,類似 memsetfill_n(g, N*N, false);for (int i = 1; i <= m; ++i) {int u, v;cin >> u >> v;g[u][v] = true;   // u->v 有條單向邊// 如果是雙向邊// g[u][v] = g[v][u] = true;}return 0;
}

復雜度

查詢是否存在某條邊:?𝑂(1)O(1)?。

遍歷一個點的所有出邊:?𝑂(𝑛)O(n)?。

遍歷整張圖:?𝑂(𝑛2)O(n2)?。

空間復雜度:?𝑂(𝑛2)O(n2)?。

應用

鄰接矩陣只適用于沒有重邊(或重邊可以忽略)的情況。

其最顯著的優點是可以?𝑂(1)O(1)?查詢一條邊是否存在。

由于鄰接矩陣在稀疏圖上效率很低(尤其是在點數較多的圖上,空間無法承受),所以一般只會?在稠密圖上使用鄰接矩陣。并且,在稠密圖上使用鄰接矩陣的運行效率遠高于鄰接表,這是因為 CPU 中順序訪問的速度是遠高于隨機訪問的(緩存命中)。

圖片

鄰接表

方法

使用一個支持動態增加元素的數據結構構成的數組,如?vector<int> g[N]?來存邊,其中?g[u]?存儲的是點?𝑢u?的所有出邊的相關信息(終點、邊權等)。

#include <iostream>
#include <vector>
using namespace std;const int N = 1e5+5;
int n, m;
bool vis[N];
vector<int> g[N];bool find_edge(int u, int v) {for (int i = 0; i < g[u].size(); ++i) {if (g[u][i] == v) {return true;}}return false;
}void dfs(int u) {if (vis[u]) return;vis[u] = true;for (int i = 0; i < g[u].size(); ++i) dfs(g[u][i]);
}int main() {cin >> n >> m;vis.resize(n + 1, false);g.resize(n + 1);for (int i = 1; i <= m; ++i) {int u, v;cin >> u >> v;g[u].push_back(v);// 如果是無向圖,還須:// g[v].push_back(u);}return 0;
}

復雜度

查詢是否存在?𝑢u?到?𝑣v?的邊:?𝑂(𝑑+(𝑢))O(d+(u))?(如果事先進行了排序就可以使用 二分查找 做到?𝑂(log?(𝑑+(𝑢)))O(log(d+(u)))?)。

遍歷點?𝑢u?的所有出邊:?𝑂(𝑑+(𝑢))O(d+(u))?。

遍歷整張圖:?𝑂(𝑛+𝑚)O(n+m)?。

空間復雜度:?𝑂(𝑚)O(m)?。

應用

存各種圖都很適合,除非有特殊需求(如需要快速查詢一條邊是否存在,且點數較少,可以使用鄰接矩陣)。

尤其適用于需要對一個點的所有出邊進行排序的場合。

鏈式前向星

方法

本質上是用鏈表實現的鄰接表,示例代碼如下:

#include <iostream>
#include <vector>
using namespace std;const int N = 1e5+5;
int n, m;bool vis[N];
int head[N], nxt[N], to[N], cnt;     // 鏈式前向星三要素void add(int u, int v) {     // 添加一條 u->v 的邊nxt[++cnt] = head[u];    // cnt 這條邊的后繼(同是 u 的出邊的上一條邊)to[cnt] = v;             // 當前邊的終點是 vhead[u] = cnt;           // 起點 u 的第一條邊放到了下標 cnt 處(其實是最后一條)
}bool find_edge(int u, int v) {for (int i = head[u]; ~i; i = nxt[i]) {  // ~i 表示 i != -1if (to[i] == v) {return true;}}return false;
}void dfs(int u) {if (vis[u]) return;vis[u] = true;cout << u << ' ';for (int i = head[u]; ~i; i = nxt[i])dfs(to[i]);
}int main() {cin >> n >> m;fill_n(vis, N, false);fill_n(head, N, -1);for (int i = 1; i <= m; ++i) {int u, v;cin >> u >> v;add(u, v);}dfs(1);return 0;
}

如果圖是賦權圖,即邊帶有權重時,此時數組定義過多,也可以寫成結構體去保存,參考代碼如下:

#include<bits/stdc++.h>
using namespace std;const int N = 1e5;    //點數最大值
int n, m;             //n個點,m條邊
int head[N], cnt = -1;     //head[i],表示以i為起點的第一條邊在邊集數組的位置(編號)struct Edge
{int to, w, next;   // 終點,邊權,同起點的上一條邊的編號
}edge[N];//邊集void add_edge(int u, int v, int w)// 加邊,u 起點,v 終點,w 邊權
{edge[++cnt].next = head[u];    // 以u為起點上一條邊的編號,也就是與這個邊起點相同的上一條邊的編號edge[cnt].to = v;          // 終點edge[cnt].w = w;             // 權值head[u] = cnt;               // 更新以u為起點上一條邊的編號
}
int main()
{cin >> n >> m;int u, v, w;fill_n(head, N, -1);for (int i = 1; i <= m; i++) // 輸入m條邊{cin >> u >> v >> w;add_edge(u, v, w);       // 加邊// 加雙向邊// add_edge(u, v, w);// add_edge(v, u, w);}// 輸出每個結點的出邊for (int i = 1; i <= n; i++){cout << i << endl;for (int j = head[i]; ~j; j = edge[j].next)  // 遍歷以 i為起點的邊{cout << i << " " << edge[j].to << " " << edge[j].w << endl;}cout << endl;}return 0;
}
/*
5 7
1 2 1
2 3 2
3 4 3
1 3 4
4 1 5
1 5 6
4 5 7
*/

復雜度

查詢是否存在?𝑢u?到?𝑣v?的邊:?𝑂(𝑑+(𝑢))O(d+(u))?。

遍歷點?𝑢u?的所有出邊:?𝑂(𝑑+(𝑢))O(d+(u))?。

遍歷整張圖:?𝑂(𝑛+𝑚)O(n+m)?。

空間復雜度:?𝑂(𝑚)O(m)?。

應用

注意:利用鏈式前向星遍歷的邊的順序和輸入順序是相反的!

存各種圖都很適合,但是缺點也很明顯,?不能快速查詢一條邊是否存在,也不能方便地對一個點的出邊進行排序

優點是邊是帶編號的,有時會非常有用,而且如果邊是從數組的偶數位開始存儲( 按上面示例代碼寫法是從 0 開始存儲的,cnt?的初始值為 -1),存雙向邊時?i ^ 1?即是?i?的反邊(常用于網絡流 )。

總結

圖的存儲方法比較多,每種方法各有優缺點,對比如下:

直接存邊鄰接矩陣鄰接表鏈式前向星
使用場合需要將邊按邊權排序時;需要重新建圖時利用直接存下的邊來建圖只適用于沒有重邊(或重邊可以忽略)的情況;可以?𝑂(1)O(1)?查詢邊;在稠密圖上效率很高消耗空間較小,各種場合都適用,尤其適用于需要對點的出邊排序的場合消耗空間小,各種場合都適用
缺點遍歷效率低下,一般不用于遍歷圖只適用于沒有重邊(或重邊可以忽略)的情況。需熟練掌握 vector 操作?不能迅速查詢邊和對一個點的出邊排序

總的來說,就是:

  1. 需要對所有邊進行排序時,直接存邊;
  2. 圖很稠密,用鄰接矩陣;
  3. 其他一般情況,用鄰接表或鏈式前向星都可以。

請在理解各種方法的優缺點并掌握其代碼實現以后,面對具體問題應思考選擇合適的方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/11585.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/11585.shtml
英文地址,請注明出處:http://en.pswp.cn/web/11585.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pytorch如何計算網絡參數

方法一. 利用pytorch自身 PyTorch是一個流行的深度學習框架&#xff0c;它允許研究人員和開發者快速構建和訓練神經網絡。計算一個PyTorch網絡的參數量通常涉及兩個步驟&#xff1a;確定網絡中每個層的參數數量&#xff0c;并將它們加起來得到總數。 以下是在PyTorch中計算網…

如何在 CloudFlare 里屏蔽/攔截某個 IP 或者 IP 地址段

最近除了接的 CloudFlare 代配置訂單基本很少折騰自己的 CloudFlare 配置了,今天給大家簡單的講解一下如何在 CloudFlare 里屏蔽/攔截 IP 地址和 IP 地址段,雖然明月一直都很反感針對 IP 的屏蔽攔截,但不得不說有時候還是很有必要的。并且,既然可以攔截屏蔽 IP 自然也可以但…

鴻蒙內核源碼分析(VFS篇) | 文件系統和諧共處的基礎

基本概念 | 官方定義 VFS&#xff08;Virtual File System&#xff09;是文件系統的虛擬層&#xff0c;它不是一個實際的文件系統&#xff0c;而是一個異構文件系統之上的軟件粘合層&#xff0c;為用戶提供統一的類Unix文件操作接口。由于不同類型的文件系統接口不統一&#x…

Flink HA模式下JobManager切換時發送告警

資源&版本信息 Flink版本1.14.6 運行平臺&#xff1a;K8s HA使用ZK&#xff08;使用K8s的ETC應該是一個道理&#xff09; 詳解Flink HA原理 Flink啟動時會創建HighAvailabilityServices提供HA和相關基礎服務&#xff0c;其中包括leaderRetrievalService和LeaderElecti…

搜索引擎的設計與實現(二)

目錄 3 搜索引擎的基本原理 3.1搜索引擎的基本組成及其功能 l.搜索器 (Crawler) 2.索引器(Indexer) 3.檢索器(Searcher) 4.用戶接口(UserInterface) 3.2搜索引擎的詳細工作流程 4 系統分析與設計 4.1系統分析 4.2系統概要設計 4.2系統實現目標 前面內容請移步 搜索引…

Rust 語言不支持 goto 語句

一、Rust 不提供 goto 語句 Rust 語言并沒有提供 goto 語句。goto 語句在很多現代編程語言中已經不再被推薦使用&#xff0c;因為它可能導致代碼的流程變得難以跟蹤和理解&#xff0c;特別是在復雜的程序中。Rust 語言設計者選擇了更加結構化和可預測的控制流語句&#xff0c;…

關于C++多態的復習總結

多態 簡介: 面向對象的三大特性之一&#xff0c;多態顧名思義即具有多種形態&#xff0c;即去執行某個行為時&#xff0c;當不同的對象去執行時會產生不同的狀態 構成多態的條件 條件一 必須通過基類&#xff08;父類&#xff09;的指針或者引用調用虛函數&#xff08;函數…

寧夏銀川市起名專家的老師顏廷利:死神(死亡)并不可怕,可怕的是...

在中國優秀傳統文化之中&#xff0c;漢語‘巳’字與‘四’同音&#xff0c;在阿拉伯數字里面&#xff0c;通常用‘4’來表示&#xff1b; 湖南長沙、四川成都、重慶、寧夏銀川最靠譜最厲害的起名大師的老師顏廷利教授指出&#xff0c;作為漢語‘九’字&#xff0c;倘若是換一個…

FreeRTOS中斷管理

FreeRTOS中斷管理 基于STM32_stm32 freertos 按鍵中斷-CSDN博客 更加詳情請看以上鏈接↑ 中斷優先級 任何中斷的優先級都大于任務! 在我們的操作系統,中斷同樣是具有優先級的,并且我們也可以設置它的優先級,但是他的優先 級并不是從 0~15 ,默認情況下它是從 5~15 ,…

[ACTF新生賽2020]SoulLike

沒見過的錯誤&#xff1a; ida /ctg目錄下的hexrays.cfg文件中的MAX_FUNCSIZE64 改為 MAX_FUNCSIZE1024 然后就是一堆數據 反正就是12個字符 from pwn import * flag"actf{" k0 for n in range(12):for i in range(33,127):pprocess("./SoulLike")_flag…

94.二叉樹的中序遍歷

刷算法題&#xff1a; 第一遍&#xff1a;1.看5分鐘&#xff0c;沒思路看題解 2.通過題解改進自己的解法&#xff0c;并且要寫每行的注釋以及自己的思路。 3.思考自己做到了題解的哪一步&#xff0c;下次怎么才能做對(總結方法) 4.整理到自己的自媒體平臺。 5.再刷重復的類…

Python爬蟲入門:網絡世界的寶藏獵人

今天阿佑將帶你踏上Python的肩膀&#xff0c;成為一名網絡世界的寶藏獵人&#xff01; 文章目錄 1. 引言1.1 簡述Python在爬蟲領域的地位1.2 闡明學習網絡基礎對爬蟲的重要性 2. 背景介紹2.1 Python語言的流行與適用場景2.2 網絡通信基礎概念及其在數據抓取中的角色 3. Python基…

今日總結2024/5/13

今日學習了01背包求具體方案的方法 Acwing.12 背包問題求具體方案 由于背包是從小到大枚舉物品&#xff0c;只能從后往前判斷是從哪個狀態遞推過來的&#xff0c;而該題要求按字典序順序輸出字典序最小的最優方案 因此要將物品從大到小枚舉&#xff0c;判斷時從小到大判斷是…

在Windows上有哪些好用的網絡抓包工具?

2024年5月12日&#xff0c;周日上午 在Windows上&#xff0c;有多種好用的網絡抓包工具&#xff0c;以下是一些常見的選項&#xff1a; Wireshark&#xff1a; Wireshark 是一款功能強大的網絡協議分析工具&#xff0c;它可以捕獲并分析計算機網絡上的數據包。它支持廣泛的協議…

ssm+vue的公務用車管理智慧云服務監管平臺查詢統計(有報告)。Javaee項目,ssm vue前后端分離項目

演示視頻&#xff1a; ssmvue的公務用車管理智慧云服務監管平臺查詢統計&#xff08;有報告&#xff09;。Javaee項目&#xff0c;ssm vue前后端分離項目 項目介紹&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&…

求階乘n!末尾0的個數溢出了怎么辦

小林最近遇到一個問題&#xff1a;“對于任意給定的一個正整數n&#xff0c;統計其階乘n&#xff01;的末尾中0的個數”&#xff0c;這個問題究竟該如何解決&#xff1f; 先用n5來解決這個問題。n的階乘即n!5!5*4*3*2*1120&#xff0c;顯然應該為2個數相乘等于10才能得到一個結…

軟件測試自動化:加速測試,提升效率

目錄 測試自動化的內涵 測試自動化的原理 測試工具的分類和選擇 自動化測試的引入 在當今的軟件開發中&#xff0c;測試自動化已經成為提升效率和確保軟件質量的關鍵環節。測試自動化是指使用軟件工具和腳本來執行重復的測試任務&#xff0c;從而減輕人工測試的負擔&#x…

量化交易包含些什么?

我們講過許多關于量化交易的內容&#xff0c;但是量化交易具體可以做些什么&#xff1f;很多朋友都還不清楚&#xff0c;我們詳細來探討下&#xff01; 第一&#xff1a;什么是量化交易&#xff1f; 量化交易是一種利用先進的數學模型和計算機技術&#xff0c;從大量的歷史數…

制造業精益生產KPI和智慧供應鏈管理方案和實踐案例分享

隨著工業4.0的推進和國家對制造業高質量發展的重視&#xff0c;工業數據已躍升為生產經營活動中不可或缺的核心要素&#xff0c;同時&#xff0c;工業數據也是形成新質生產力的優質生產要素&#xff0c;助力企業實現高效精益生產。 工業數據在制造業中的作用不可忽視&#xff…

常見地圖坐標系間的轉換算法JavaScript實現

文章目錄 ?? 不同的地圖廠商使用不同的坐標系來表示地理位置。以下簡述:?? 前置常量和方法:?? BD-09轉GCJ-02(百度轉谷歌、高德)?? GCJ-02轉BD-09(谷歌、高德轉百度)?? WGS84轉GCJ-02(WGS84轉谷歌、高德)?? GCJ-02轉WGS84(谷歌、高德轉WGS84)?? BD-09轉wgs84坐…