7 11最小生成樹 最短路

2022-07-31 03:15:13 字數 2955 閱讀 4245

其實這一部分的知識在前面我也算是學了一些了,今天老師講的是一些應用部分,結果我發現自己一臉懵逼,有些題我甚至連這是最短路都沒有看出來。看來還並沒有修煉到一定的水準,並且我還是發現一些自己還沒有學習過的知識,下面我們就先從鏈式前向星開始說起。

首先我們就來介紹一下這個東西是個什麼。

圖的儲存一般有兩種:鄰接矩陣,前向星。

若圖是稀疏圖,邊很少,開二維陣列是非常浪費的。

若點非常的多,(如10000個點)開二維陣列就會爆空間,所以說只能用前向星來做。

前向星的效率不是很高,優化後變成鏈式前向星,效率有所提公升。

(1)結構

這裡有兩個東西

1、結構體陣列edge存邊,edge[i]表示第i條邊。

2、head[i]存以i為起點的第一條邊(在egde中的下標)

注意:每次新加的邊作為第一條邊!!!

struct edge; 

edge edge[500010];

2.增邊:若以點i為起點的邊新增了一條,在edge中的下標為j.

那麼edge[j].next=head[i];然後head[i]=j.

即每次新加的邊作為第一條邊,最後倒序遍歷

void add(int u, int v, int w)
3、遍歷

遍歷以st為起點的邊

for(int i=head[st]; i!=0; i=edge[i].next)
i開始為第一條邊,每次指向下一條(以0為結束標誌) (若下標從0開始,next應初始化-1)important!!

下面是自己用鏈式前向星寫的spfa:

**如下:

#includeusing namespace std;

int dis[10005];

struct sdedge[500005];

int head[10005];

bool vis[10005];

int cnt=0;

int n,m,s;

void add(int from,int to,int val)

void spfa()

queueq;

q.push(s);

dis[s]=0;

vis[s]=true;

while(!q.empty())

}} }

}int main()

spfa();

for(int i=1;i<=n;++i)

return 0;

}

dijsktra priority版本的鏈式前向星版本後面再說。

下面進入今天的正題,我們以一道例題來感受一下圖論中建圖的奧妙,雖然這道題本人自己想了很久也並沒有做出來,但是,我已經深刻的理解到了題解中的做法,所以說呢,這裡所用的**並不是本人自己寫的,大家理解一下,畢竟是「noi」難度的,所用我覺得還是有一些困難:

下面我們就上題吧!

題目傳送門:p3645 [apio2015]耶加達的摩天樓

這道題其實看上去並沒有想象中的那麼難,但是如果你那樣想的話,很可能是因為你並沒有注意到資料範圍上的限制,這道題對資料範圍的限制可以說還是比較厲害的,所以想直接暴力建圖的同學最好還是在仔細考慮一下到底行不行,反正我試過是不行的,那麼我們如何縮小我們建圖所耗費的時間複雜度呢?其實,我們這樣想就好了,我們把所有能力小於sqrt(n)的doge所有邊的可能情況都先把圖建出來,然後如果出現了能力大於sqrt(n)的doge我們就進行暴力建邊,注意:對於那些能力是0的doge我們要從高層的圖中往最底層建一條權值為0的又向邊,然後對於那些我們加進來有p能力但是能力沒有超過sqrt(n)的doge我們要從最底層建一條到第p層權值為0的有向邊,這樣他的能力才能得到發揮(因為我們小於sqrt(n)的能力的邊是已經經過我們預處理過的,我們不是像大於sqrt(n)的能力的doge一樣是直接在他所在的位置進行暴力建邊)。最後這些工作都做完了以後,咱們最難的一部分建圖就已經搞定了,接下來只需要跑乙個spfa或dijsktra就可以了。相信大家都應該聽懂了吧!**中也有注釋,不懂的還可以再看一看:

**如下:

#include#define rg register

#define il inline

#define n 5500000

#define inf 2

#define u unsigned short

#define pos(i,j) (i*n+j)

using namespace std;

struct ede[30005*500];

int head[30005*105],dis[30005*105],n,m,q,b,s,t;

bool in[30005*105];

int tot;

void add(int u,int v,int c)

void add(int u,int v,int c)

void spfa()

}if(dis[t]==ss)cout<

else cout<>n>>m;u int len=min((int)sqrt(n),100);//下面四個for迴圈是來加短邊的 ,其中每一行的第乙個for迴圈是用來建第i層圖的,第i層圖doge的跳躍能力為i

for(rg int i=1;i<=len;++i)for(int j=1;j<=n;++j)add(pos(i,j),j,0);//單獨判斷跳躍能力是0doge

for(rg int i=1;i<=len;++i)for(int j=1;j<=n-i;++j)add(pos(i,j),pos(i,j+i),1);//新增從j到所有j可以到的最短的邊的路徑

for(rg int i=1;i<=m;++i)

}spfa();

return 0;

}

by nj

最短路徑 最小生成樹

題目描述 n個城市,標號從0到n 1,m條道路,第k條道路 k從0開始 的長度為2 k,求編號為0的城市到其他城市的最短距離 輸入描述 第一行兩個正整數n 2 n 100 m m 500 表示有n個城市,m條道路 接下來m行兩個整數,表示相連的兩個城市的編號 輸出描述 n 1行,表示0號城市到其他城...

最短路徑 最小生成樹

今天覆習的時候,剛好複習的這一塊,所以就簡單做乙個備忘,寫的潦草還望大家不要介意呀 1 dijistra演算法 思路 根據點集合將其分為兩個集合,一種是已經訪問過的點s集合 代表從源點到該集合中的點的距離最小 另一種是未訪問過的u集合,然後每次從u集合中選擇節點,使得源點到改點的距離最小,並新增進s...

最短路徑,最短路徑樹和最小生成樹

首先介紹這三個概念,很多人都聽過最短路徑了,但是最短路徑樹卻很少聽過,關於最短路徑樹的介紹也不太多。而最短路徑樹和最小生成樹更是完全不同的兩個概念。最短路徑就是從乙個指定的頂點出發,計算從該頂點出發到其他所有頂點的最短路徑。通常用dijkstra演算法,floyd演算法求解。最短路徑樹spt sho...