邻接表的存储方式如下
注意:我所说的节点和点表示的意思是有区别的!!
先用一个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++;
}