關於鏈式前向星及其簡單運用

2021-09-02 18:59:40 字數 3948 閱讀 5478

首先來一段網上關於前向星的描述:

前向星是一種特殊的邊集陣列,我們把邊集陣列中的每一條邊按照起點從小到大排序,如果起點相同就按照終點從小到大排序,

並記錄下以某個點為起點的所有邊在陣列中的起始位置和儲存長度,那麼前向星就構造好了.

用len[i]來記錄所有以i為起點的邊在陣列中的儲存長度.

用head[i]記錄以i為邊集在陣列中的第乙個儲存位置.

再來一段另外的乙個介紹

圖的儲存一般有兩種:鄰接矩陣、鄰接表(鄰接表包括一種東西叫前向星)。

若圖是稀疏圖,邊很少,開二維陣列a很浪費;

若點很多(如10000個點)a[10000][10000]又會爆.只能 前向星做.

前向星的效率不是很高,優化後為鏈式前向星,直接介紹鏈式前向星。

我們輸入邊的順序為:

1 22 3

3 41 3

4 11 5

4 5那麼排完序後就得到:

編號:     1      2      3      4      5      6      7

起點u:    1      1      1      2      3      4      4

終點v:    2      3      5      3      4      1      5

但是利用前向星會有排序操作,如果用快排時間至少為o(nlog(n))

如果用鏈式前向星,就可以避免排序.

那麼我們先來建立乙個結構體

struct nodeedge[maxn];
再來看一段比較重要的**,具體看注釋 

void add(int u, int v, int w)
下面來看一段網上摘抄的**來簡單理解鏈式前向星,結構體設定的有些不一樣,不過不影響閱讀;

我們來對該圖的輸入輸出做乙個分析

注意cnt的初值我們初始化為1 cnt

edge[1].next = head[1] = 0, head[1] = 1, 2 ;

edge[2].next = head[2] = 0, head[2] = 2, 3 ;

edge[3].next = head[3] = 0, head[3] = 3, 4 ;

edge[4].next = head[1] = 1, head[1] = 4, 5 ;

edge[5].next = head[4] = 0, head[4] = 5, 6 ;

edge[6].next = head[1] = 4, head[1] = 6, 7 ;

我們可以看出cnt的值一直在變,其實可以理解為陣列的下標,然後head值得就是指向該邊的上一條邊的下標,這個還得靠自己結合**悟,我也一時無法解釋清楚

在這裡我們可以更加深入理解head陣列的作用,說實話我也是看了這個才明白他的真正的作用,關於他的遍歷是倒著來的,一直到初始值,初始值根據需要設定為-1或者0

接下來我們來看乙個題目,運用到了並查集與鏈式前向星,根據這個題目我們來更熟悉一下他的運用:

很久以前,在乙個遙遠的星系,乙個黑暗的帝國靠著它的超級**統治著整個星系。

某一天,憑著乙個偶然的機遇,一支反抗軍摧毀了帝國的超級**,並攻下了星系中幾乎所有的星球。這些星球通過特殊的以太隧道互相直接或間接地連線。

但好景不長,很快帝國又重新造出了他的超級**。憑藉這超級**的力量,帝國開始有計畫地摧毀反抗軍占領的星球。由於星球的不斷被摧毀,兩個星球之間的通訊通道也開始不可靠起來。

現在,反抗軍首領交給你乙個任務:給出原來兩個星球之間的以太隧道連通情況以及帝國打擊的星球順序,以盡量快的速度求出每一次打擊之後反抗軍佔據的星球的連通塊的個數。(如果兩個星球可以通過現存的以太通道直接或間接地連通,則這兩個星球在同乙個連通塊中)。

輸入格式:

輸入檔案第一行包含兩個整數,nn (1 < = n < = 2m1<=n<=2m) 和 mm (1 < = m < = 200,0001<=m<=200,000),分別表示星球的數目和以太隧道的數目。星球用 00 ~ n-1n−1 的整數編號。

接下來的 mm 行,每行包括兩個整數 xx, yy,其中( 0 < = x <> y0<=x<>y 表示星球 xx 和星球 yy 之間有 「以太」 隧道,可以直接通訊。

接下來的一行為乙個整數 kk ,表示將遭受攻擊的星球的數目。

接下來的 kk 行,每行有乙個整數,按照順序列出了帝**的攻擊目標。這 kk 個數互不相同,且都在 00 到 n-1n−1 的範圍內。

輸出格式:

第一行是開始時星球的連通塊個數。接下來的 kk 行,每行乙個整數,表示經過該次打擊後現存星球的連通塊個數。

輸入樣例#1:複製

8 13

0 11 6

6 55 0

0 61 2

2 33 4

4 57 1

7 27 6

3 6516357

輸出樣例#1:複製

111233

附送一段題解**:

// luogu-judger-enable-o2

#include#define ios ios::sync_with_stdio(false)

using namespace std;

const int maxn = 4e5 + 4;

int father[maxn], head[maxn], store[maxn], ans[maxn];

int cnt = 0;

bool vis[maxn];

struct nodeedge[maxn];

//和一般的前向星還是有一些小小的差別

void insert(int u, int v)

int findfather(int x)

int union(int a, int b)

return 0;

}//和一般的思路不一樣,我們假設所有的星球都是毀滅的,然後每次修復好乙個星球,並且將結果儲存到陣列裡,最後輸出即可,這樣可以有個更好的思路

int main()

for (int i = 0; i < m; i++)

cin >> k;

int total = n - k;//假設全部都是毀滅狀態

for (int i = 0; i < k; i++)

for (int i = 0; i < 2 * m; i++)

}ans[k] = total;

for (int i = k - 1; i >= 0; i--)

}ans[i] = total;

}for (int i = 0; i <= k; i++)

return 0;

}

關於鏈式前向星還可以看看其他部落格,不過很多題目都運用到了這個技巧,例如spfa使用鏈式前向星之類的,之後再刷題目的過程中會慢慢熟悉的

前向星和鏈式前向星

我們首先來看一下什麼是前向星.前向星是一種特殊的邊集陣列,我們把邊集陣列中的每一條邊按照起點從小到大排序,如果起點相同就按照終點從小到大排序,並記錄下以某個點為起點的所有邊在陣列中的起始位置和儲存長度,那麼前向星就構造好了.用len i 來記錄所有以i為起點的邊在陣列中的儲存長度.用head i 記...

前向星和鏈式前向星

前向星 前向星是一種特殊的邊集陣列,我們把邊集陣列中的每一條邊按照起點從小到大排序,如果起點相同就按照終點從小到大排序,並記錄下以某個點為起點的所有邊在陣列中的起始位置。鏈式前向星 鏈式前向星其實就是靜態建立的鄰接表,時間效率為o m 空間效率也為o m 遍歷效率也為o m next表示當前結點的下...

前向星和鏈式前向星

1 前向星 前向星是以儲存邊的方式來儲存圖,先將邊讀入並儲存在連續的陣列中,然後按照邊的起點進行排序,這樣陣列中起點相等的邊就能夠在陣列中進行連續訪問了。它的優點是實現簡單,容易理解,缺點是需要在所有邊都讀入完畢的情況下對所有邊進行一次排序,帶來了時間開銷,實用性也較差,只適合離線演算法。圖一 2 ...