用邻接表实现spfa

来源:互联网 发布:数据库设计步骤 编辑:程序博客网 时间:2024/06/10 08:58

邻接表的存储方式如下



注意:我所说的节点和点表示的意思是有区别的!!

先用一个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;//初始化为 0int head[50];//初始化为 -1void 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++;}


0 0
原创粉丝点击