单源最短路

来源:互联网 发布:kbar软件下载 编辑:程序博客网 时间:2024/05/01 22:51

/*

     1.开一个二维数组记录从点A到点B需要的距离,road[MAXN][MAXN]需要初始化为MAX

     开一个vis(记录是否被访问)和dis(记录从源头到该点的最短路)数组,开一个队列

     2.spfa

        初始化vis为0,dis为MAX,源头vis为1,dis为0,将源头放入队列

        当队列不为空时执行循环

              cur为队首,并将其弹出队列

             从1到n循环,若dis[i]>dis[cur]+road[cur][i]

                  dis[i]=dis[cur]+road[cur][i];

                  如果vis[i]==0,vis[i]=1,并将其放入队列

             循环结束,vis[cur]=0;

 */

constint MAX=999999999;

constint MAXN=105;

introad[MAXN][MAXN],vis[MAXN],dis[MAXN],n,m;

queue<int> q;

int spfa(int x)

{

     int i;

     memset(vis,0,sizeof(vis));

     for(i=1;i<=n;i++)dis[i]=MAX;

     q.push(x);

     vis[x]=1;

     dis[x]=0;

     while(!q.empty()){

         int cur=q.front();

         q.pop();

         for(i=1;i<=n;i++)

         {

              if(dis[i]>dis[cur]+road[cur][i])

              {

                   dis[i]=dis[cur]+road[cur][i];

                   if(!vis[i])

                   {

                       vis[i]=1;

                       q.push(i);

                   }

              }

         }

         vis[cur]=0;

     }

     return dis[n];

}

int main()

{

     int i,a,b,c;

     while(cin>>n>>m&&(n||m))

     {

         for(i=1;i<=n;i++)

              for(intj=1;j<=n;j++)road[i][j]=MAX;

         for(i=1;i<=m;i++){

              cin>>a>>b>>c;

              road[a][b]=road[b][a]=c;

         }

         cout<<spfa(1)<<endl;

     }

     return 0;

}

//版本二

const int MAX=99999999;

const int MAXN=300005;

const int MAXM=1000005;

intn,m,k,q,dis[MAXN],vis[MAXN],head[MAXN]//以改点为起点的边在数组的哪个位置;

struct Edge

{

     int u,w,next//记录同一起点的下一条边在数组的哪个位置;

}edge[MAXM];

void spfa(int s)

{

     int i,t,u,w;

     queue<int>q;

     memset(vis,0,sizeof(vis));

     for(i=0;i<MAXN;i++)dis[i]=MAX;

     dis[s]=0;

     q.push(s);

     while(!q.empty())

     {

         t=q.front();

         q.pop();

         for(i=head[t];i!=-1;i=edge[i].next)

         {

              u=edge[i].u;

              w=edge[i].w;

              if(dis[u]>dis[t]+w)

              {

                   dis[u]=dis[t]+w;

                   if(vis[u]==0)

                   {

                       vis[u]=1;

                       q.push(u);

                   }

              }

         }

         vis[t]=0;

     }

}

int main()

{

     inti,a,b,c,num=0;

     memset(head,-1,sizeof(head));

     scanf("%d%d %d %d",&n,&m,&k,&q);

     n++;

     for(i=0;i<m;i++)

     {

         scanf("%d%d %d",&a,&b,&c);

         edge[num].u=b;//u为终点

         edge[num].w=c;//c为距离

         edge[num].next=head[a];//保存以a为起点的上一条边在数组的位置

         head[a]=num++;//位置更新

         edge[num].u=a;

         edge[num].w=c;

         edge[num].next=head[b];

         head[b]=num++;

     }

     for(i=0;i<k;i++)

     {

         scanf("%d",&a);

         edge[num].u=a;

         edge[num].w=0;

         edge[num].next=head[n];

         head[n]=num++;

     }

     spfa(n);

     for(i=0;i<q;i++)

     {

         scanf("%d",&a);

         if(dis[a]==MAX)

         {

              printf("-1\n");

         }

         elseprintf("%d\n",dis[a]);

     }

     return 0;

}

 

0 0