zoj 1053 FDNY to the Rescue!

求最短路径Dijkstra,反向建边。

注意初始位置和目标位置相同时,最短路径上只有一个交叉路口。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 100000
#define MAX 21

using namespace std;
struct Node{

 int index;
 int dis;
   bool operator <(const Node &b)const
    {
        return dis<b.dis;
    }
 };
 Node orgn[MAX];
 int n;
 int dist[MAX];
 int edge[MAX][MAX];
 int path[MAX];
 int s[MAX];

 void Dijkstra(int v0)
 {

     int i,j,k;
     for(i=1; i<=n; i++)
     {
        dist[i]=edge[v0][i] ;
        s[i]=0;
        if(i!=v0&&dist[i]<INF)path[i]=v0;
        else path[i]=-1;
     }
     s[v0]=1,dist[v0]=0;
    for(i=0; i<n-1; i++)
    {
        int min=INF;
        int u=v0;

        for(j=1; j<=n; j++)
        {
            if(!s[j]&&dist[j]<min)
            {
                min=dist[j];
                u=j;
            }
        }

        s[u]=1;
        for(k=1; k<=n; k++)
        {
         if(!s[k]&&edge[u][k]<INF&&dist[u]+edge[u][k]<dist[k])
            {
            dist[k]=dist[u]+edge[u][k];
           path[k]=u;
            }
        }
    }
 }

 int main()
 {
     bool flag=0;
     int T,dest;
     int i,j;
     char org[21];
     cin>>T;
     while(T--)
     {
         cin>>n;
         getchar();
         for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
         {
             cin>>edge[i][j];
             if(edge[i][j]==-1)edge[i][j]=INF;

         }
        for(i=1;i<=n;edge[i][i]=0,i++)
	      for(j=i+1;j<=n;j++)
	      swap(edge[i][j],edge[j][i]);

         gets(org);
         gets(org);
         dest=org[0]-'0';

         int k=0;
         for(i=2; i<strlen(org); i+=2)
         {
             orgn[k++].index=org[i]-'0';

         }
        Dijkstra(dest);
        if(flag)cout<<endl;
        else flag=true;
        for(i=0; i<k; i++)
        {
            orgn[i].dis=dist[orgn[i].index];
        }
        sort(orgn,orgn+k);
         printf("Org\tDest\tTime\tPath\n");
         for(i=0; i<k; i++)
         {
             int temp=orgn[i].index;
    printf("%d\t%d\t%d\t%d",temp,dest,dist[temp],temp);
           if(dest==temp)
           {printf("\n");
            continue;
           }
             while(path[temp]!=dest)
             {

                 printf("\t%d",path[temp]);
                  temp=path[temp];

             }

              printf("\t%d\n",dest);
         }
     }
       return 0;
 }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值