春游 迪杰斯特拉+并查集

  1. 定义了一个图的数据结构,包括邻接矩阵a和b,顶点数vex,最小值mins和边数arm。其中,邻接矩阵a用于存储边的权重(距离),邻接矩阵b用于存储边的耗时。

  2. 创建图的函数creatgp,输入图的顶点数、边数和最小值,然后初始化邻接矩阵a和b,将邻接矩阵a的对角线元素设为0,表示顶点到自身的距离为0,其他元素设为最大值maxxs,表示顶点之间没有直接连接;将邻接矩阵b的元素设为最大值timersmax,表示顶点之间没有直接连接。然后根据输入的边的信息,更新邻接矩阵a和b。

  3. 打印路径的函数print,输入图、距离数组dist、路径数组path、标记数组s和时间数组timer,输出从起点到终点的最短路径及其耗时和距离。

  4. 实现Dijkstra算法的函数dj,输入图,计算从起点到各个顶点的最短距离、最短路径和最短耗时,然后调用print函数输出结果。

  5. main函数,创建图p,调用creatgp函数创建图,然后调用dj函数求解最短路径问题。#include<bits/stdc++.h>

  6. using namespace std;

  7. #define max 1001

    #define maxxs 10008660

    #define timersmax 1000777

    typedef struct{

      int a[max][max];//代表时间图

      int b[max][max];//定义图  路程图

      int vex;

      int mins;

      int arm;

    }*graph,Graph;

    void creatgp(graph &p)//创建

    {

      if(p==NULL)

      {

        p=new Graph;

        cin>>p->vex>>p->arm>>p->mins;

      }

      for(int i=0;i<max;i++)

      {

        for(int j=0;j<max;j++)

        {

          p->a[i][j]=maxxs;

          p->b[i][j]=timersmax;

          if(i==j)

            p->a[i][j]=0;

        }

      }

      for(int i=1;i<=p->arm;i++)

      {

        int x,y,time,dist;

        cin>>x>>y>>time>>dist;

        p->a[x][y]=dist;

        p->a[y][x]=dist;

        p->b[x][y]=time;

        p->b[y][x]=time;

      }

    }

    void print(graph &p,int *dist,int *path,int *s,int *timer)

    {

      int apath[max];

      int k=p->mins;

      int d=0;

      apath[d]=k;

      cout<<timer[k]<<" "<<dist[k]<<" ";

      int times=0;

      k=path[k];

      while(k!=1)

      {

        d++;

        apath[d]=k;

        k=path[k];

      }

      cout<<"1";

      for(;d>=0;d--)

      {

        cout<<"->"<<apath[d];

      }

    }

    void dj(graph &p)//注意  这道题的时间权重大于路程   所以遍历时先比较时间 时间相等时比较路程

    {

      int dist[max];

      int s[max]={0};

      int path[max];

      int timer[max];

      for(int i=1;i<=p->vex;i++)

      {

        if(p->a[1][i]!=0&&p->a[1][i]<maxxs)//初始并查集

          path[i]=1;

        else path[i]=0;

      }

      for(int i=1;i<=p->vex;i++)

      {

        dist[i]=p->a[1][i];

        if(p->b[1][i]!=0&&p->b[1][i]<timersmax)//初始化 时间数组和路程数组

        timer[i]=p->b[1][i];

        else{

          timer[i]=timersmax;

        }

      }

      s[1]=-1;

      for(int i=2;i<=p->vex;i++)

      {

        int min=maxxs;

        int k = 1;

        int timemin=timersmax;

        for(int j=1;j<=p->vex;j++)

        {

          if(s[j]!=-1)

          {

            if(timer[j]!=0&&timemin>timer[j])//这里先比较时间  

            {

              k=j;

              timemin=timer[j];

              min=dist[j];

            }

            else if(timer[j]!=0&&timemin==timer[j])//时间相等时比较路程

            {

              if(min>dist[j])

              {

                k=j;

                min = dist[j];

              }

            }

          }

        }

        s[k]=-1;

        for(int j=1;j<=p->vex;j++)

        {

          if(s[j]!=-1)

          {

            if(timer[k]+p->b[k][j]<timer[j])//跟新数据如上

            {

              timer[j]=timer[k]+p->b[k][j];

              path[j]=k;

              dist[j]=dist[k]+p->a[k][j];

            }

            else if(timer[k]+p->b[k][j]==timer[j])

            {

              if(dist[j]>dist[k]+p->a[k][j])

              {

                path[j]=k;

                dist[j]=dist[k]+p->a[k][j];

              }

            }

          }

        }

      }

      print(p,dist,path,s,timer);

    }

    int main()

    {

      graph p =NULL;

      creatgp(p);

      dj(p);

      return 0;

    }

春天阳光灿烂,小宋突然心血来潮想骑自行车去学校外面玩,但是到达目的地的路线不止一条,他想尽快的到达目的地,又能不需要骑太远的路, 你能帮助他吗?

输入格式:

输入包含一个测试数据,第一行有三个整数n(2 <= n <= 1000),途中可能经过的地点的个数,地点编号1~n;m(1 <= m <= 10000),为路径的条数;d(2 <= d <= n),目的地编号;其中学校为起点,默认为1。接下来m行: x y time dist , x y表示地点x,y是可以相互到达的,time,dist分别表示x到y或y到x的时间,距离。

输出格式:

按如下格式输出“花费的时间+空格+要骑的距离+空格+从学校到达目的地的路径”,路径中的两个地点之间以箭头(->)分隔。(具体见输出样例)

输入样例:

在这里给出一组输入。例如:

7 8 7
1 2 1 1
1 3 1 1
2 4 1 2
3 4 1 1
4 5 1 2
4 6 1 1
5 7 1 1
6 7 2 1

输出输出

4 5 1->3->4->5->7
  • 21
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值