1. 程式人生 > >資料結構【鏈式前向星】

資料結構【鏈式前向星】

第一次接觸鏈式前向星是在學習圖論的迪傑斯特拉演算法時,大佬們紛紛用鏈式前向星+堆優化+迪傑斯特拉解題,秀的我萌新懵的一批,當時不知道啥是鏈式前向星,不過隨著越來越深入,這種結構見得越來越多,慢慢的就明白了。

在儲存一個圖時,我們經常用的應該是矩陣,不過他比較浪費空間,尤其是稀疏圖,點又多,空間經常爆,所以為了解決這個問題不知道那位大佬發明了前向星這個東西,不過前向星的效率不是很高,優化後為鏈式前向星,直接介紹鏈式前向星。

結構

主要是用到一個結構體和陣列頭

struct Edge{
    int next,to,w;//下一條邊的儲存下標,這條邊的終點,權值
};
Edge edge[500010];

結構體數邊緣存邊,邊[i]表示第i條邊,頭[i]存以我為起點的第一條邊(在邊中的下標)。

增邊

若以點我為起點的邊新增了一條,在邊緣中的下標為Ĵ,那麼邊緣[J]的.next =頭[I];然後頭[I] = j的,即每次新加的邊作為第一條邊,最後倒序遍歷

void Add(int u, int v, int w) {
	edge[++cnt].next = head[u];//cnt為計數,從1開始
	edge[cnt].to = v;
	edge[cnt].w = w;
	head[u] = cnt;//第一條邊為當前邊
}

遍歷

遍歷以小號為起點的邊

for(int i=head[s]; i!=0; i=edge[i].next)

我開始為第一條邊,每次指向下一條(以0為結束標誌)(若下標從0開始,下應應初始化-1)

例題:洛谷P3371

#include<bits/stdc++.h>
const long long inf=2147483647;
const int maxn=10005;
const int maxm=500005;
using namespace std;
int n,m,s,num_edge=0;
int dis[maxn],vis[maxn],head[maxm];
struct Edge{
    int next,to,dis;
}edge[maxm]; //結構體表示靜態鄰接表
void addedge(int from,int to,int dis){
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    edge[num_edge].dis=dis;
    head[from]=num_edge;
}
void spfa(){
    queue<int>q;
    for(int i=1; i<=n; i++) {
        dis[i]=inf;
        vis[i]=0;
    }
    q.push(s);
    dis[s]=0;vis[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].dis){
                dis[v]=dis[u]+edge[i].dis;
                if(vis[v]==0) {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int main(){
    cin>>n>>m>>s;
    for(int i=1; i<=m; i++){
        int f,g,w;
        cin>>f>>g>>w;
        addedge(f,g,w);
    }
    spfa();
    for(int i=1; i<=n; i++)
        if(s==i) cout<<0<<" ";
            else cout<<dis[i]<<" ";
    return 0;
}