鄰接表的存儲方式如下
注意:我所說的節點和點表示的意思是有區別的!!
先用一個list[]存所有的點。
即:
1.第一列的每一個點都在list中對應一個位置。
2.把每一個在list中的點看做源點,如圖(橫向看),每一源點都有若干個點與它連接,表示它可直接達到的點。如v1->0,v1->2,可表示所謂的”路“。橫着也是一個鏈表!
3.橫向鏈表中以NULL爲結束標誌
鄰接表的實現想了好長時間,終於想出了我認爲還可以的方法,會在代碼中說明。
以hdu 2544 最短路爲例(當然此題也可以用其他方法來做)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct node//用此結構表示橫向鏈表中的所有節點
{
node * next;//表示下一個與源點相連的節點
int p;//表示這個節點的位置,就是與源點相連的那個點;
int distance;//表示這條路徑的權值
}Node[50000+10];//有多少條有效路徑就會有多少個節點(雙向*2)
int k;//記錄用了多少個節點
node *list[100+10];//記錄源點後的第一個節點
int dis[100+10];//下面三個數組都是spfa中要用的,不多說
int vis[100+10];
int q[1000];
void func(node* &temp_,int p,int d)//建鄰接表,注意我傳的是引用,以便修改list[a]的值
{
node*temp;
if(temp_==NULL)//如果一開始源點沒有與他相連的節點
{
temp_=&Node[k++];
temp=temp_;//<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">由於傳的是引用,</span>防止再次修改temp_
}
else
{
temp=temp_;//由於傳的是引用,防止修改temp_,
while(temp->next!=NULL)
{
if(temp->p==p)
{
int t=temp->distance;
temp->distance=(t>d?d:t);
return ;
}
temp=temp->next;
}
temp->next=&Node[k++];//這點我被坑了好長時間,一定要修改temp->next的值,不然會斷鏈的
temp=temp->next;
}
temp->distance=d;
temp->next=NULL;
temp->p=p;
}
int spfa(int s,int v)//跟bfs一樣,就是點可以重複入隊
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[s]=0;
q[0]=s;
vis[s]=1;
int front=0,rear=1;
while(front<rear)
{
int temp1=q[front++];
node *temp2=list[temp1];
while(temp2!=NULL)
{
if(dis[temp2->p]>dis[temp1]+temp2->distance)
{
dis[temp2->p]=dis[temp1]+temp2->distance;
if(!vis[temp2->p])
{
q[rear++]=temp2->p;
vis[temp2->p]=1;
}
}
temp2=temp2->next;
}
vis[temp1]=0;
}
return dis[v];
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m)
break;
k=0;
for(int i=1;i<=n;i++)
list[i]=NULL;
while(m--)
{
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
func(list[a],b,v);
func(list[b],a,v);
}
int ans=spfa(1,n);
/*
for(int i=1;i<=n;i++)
{
cout<<"from "<<i<<" to"<<endl;
node *temp=list[i];
while(temp!=NULL)
{
cout<<"->";
cout<<temp->p<<ends<<temp->distance<<endl;
temp=temp->next;
}
}
*/
cout<<ans<<endl;
}
return 0;
}
由小白想到的簡潔代碼
struct Edge
{
int next;
int gohere;
int dis;
}edge[3000];
int p;//初始化爲 0
int head[50];//初始化爲 -1
void addedge(int a,int b,int dis)//a到b的路權爲dis
{
edge[p].next=head[a];
edge[p].gohere=b;
edge[p].dis=dis;
head[a]=p++;
}