代碼:

struct NODE{ int to; int nxt; int c; }node[MM];//鏈式向前星 int head[NM],lcnt=1; void add(int a,int b,int c){ node[lcnt].to=b; node[lcnt].c=c; node[lcnt].nxt=head[a]; head[a]=lcnt++; }
1.使用結構體構建鏈式向前星的容器
鏈式向前星本質上是使用鏈表存邊,一條鏈表代表着一個點發出的所有邊。所以一個這個結構體代表着這條鏈表中的一項
struct NODE{ int to; //指向下一條邊 int nxt; //指向同一個點發出的另一條邊 int c; //邊權 }node[MM];//鏈式向前星
2.第一條邊——head和邊的編號
NM是一個常量,代表着點的數量;
head代表着一條鏈表的第一個項,也就是一個點所發出的第一條邊(第一的意思是可以從這鏈表的這一項一直跳完所有項),至於如何實現請看 3 部分。
lcnt是賦予邊編號的變量,之所以初始化為1,請看 4 部分。
int head[NM];
int lcnt=1;
3.三個變量一台戲——如何加邊(add)
a,b,c分別代表入邊,出邊,權值
這個函數設置編號為lcnt的邊,將to指向的是節點編號
重點在nxt的操作上。將nxt賦值為a節點的“第一條邊”,那么就是說這個點接下來的可以跳的邊或者說鏈表的項是 head[a]
接下來將”第一條邊”賦值為當前的編號,那么下一次添加以a為源點的邊可以跳的邊或者說鏈表的項就是現在的邊或者說項了。
那就意味着最后一次添加的邊(項),可以一直跳到第一次添加的邊(項),也就符合我們在第 2 條定義的“第一條邊”了。
別忘了將編號++,以便下次使用。
void add(int a,int b,int c){ //改變編號為lcnt的邊 node[lcnt].to=b; //出邊指向b node[lcnt].c=c; //記錄權值 node[lcnt].nxt=head[a]; //將其指向目前的”第一條邊“,也就是說能跳到”第一條邊” head[a]=lcnt++; //“第一條邊”更新為目前的編號,那么下一條邊能夠跳到這一條邊,那么最后的head自然就是真正的“第一條邊”了;編號++一遍下次使用 }
4.遍歷某個點所連接的所有邊
要遍歷就可以利用前面求出的”第一條邊“和這些鏈表了。
自然可以用for,從一開始將循環變量i初始化為要遍歷的源點k的”第一條邊“,head[k]
在判斷的時候,判斷是否還有下一條邊,這時候就是lcnt初始化為1的作用了。如果沒有初始化為1,就會存在編號為0的點,判斷就會誤認為已經結束了。
於是判斷就必須寫i!=-1了,但是打"=1"只需要兩個字符,而"i!=-1"比起"i"要多4個字符,而且不符合我們人類的思維習慣:從1開始,所以我們采用lcnt初始化為1
(“i”在C++里的意思是簡寫的 i!=0 )
然后到每次循環結束做的改變,自然是直接跳到鏈表的下一項。
for(int i=head[k];i;i=node[i].nxt){ int u=node[i].to; //u就是所連接的點
int v=node[i].c;
//v就是邊的權值
}
5.注意雙向邊
如果你的題目要求是雙向邊的話,加邊操作需要進行兩次:
add(a,b,c); add(b,a,c);
注意,這時候node數組需要開兩倍於邊數的空間