最短路径问题【浙大复试】

问题描述

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

输入描述

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)

输出描述

输出 一行有两个数, 最短距离及其花费。

#include<iostream>
#include<vector>
#include<climits>
#include<queue>
#include<cstring>

using namespace std;
const int maxn=1001;
const int INF = INT_MAX;

struct edge{   //边的结构,终点,长度,花费
    int to;
    int length;
    int price;
    edge(int t,int l,int p):to(t),length(l),price(p){}
};

struct point{ //点的结构,来表示这个点到原点的距离,为了算法
    int number;
    int distance;
    point(int n,int d):number(n),distance(d){}
    bool operator<(const point&p)const{  //为了表明距离小的优先级高
        return distance>p.distance;
    }
};

vector<edge> graph[maxn];//图
int dis[maxn];
int cost[maxn];

void digkstra(int s){
    priority_queue<point>myqueue;//优先队列
    dis[s]=0;  
    cost[s]=0;
    myqueue.push(point(s,dis[s]));//最开始加进去的点就是远点自己
    while(!myqueue.empty()){
        int u =myqueue.top().number;
        myqueue.pop();
        for(int i=0;i<graph[u].size();i++){  //从u这个点开始的边有几个
            int v=graph[u][i].to;
            int l=graph[u][i].length;
            int p=graph[u][i].price;
            if((dis[v]==dis[u]+l && cost[v]>cost[u]+p)||dis[v]>dis[u]+l){
                dis[v]=dis[u]+l;
                cost[v]=cost[u]+p;
                myqueue.push(point(v,dis[v]));
            }
               
        }
    }
    return ;
}
int main(){
    int n,m;   // n是点的个数,m是边的个数
    while(cin>>n>>m){
        if(n==0&&m==0)
            break;
        memset(graph,0,sizeof(graph)); //直接初始化整个图
        fill(dis,dis+n+1,INF);         //初始化每个点到初始点的距离和花销都是最大
        fill(cost,cost+n+1,INF);
        while(m--){
            int from,to,length,price;
            cin>>from>>to>>length>>price;
            graph[from].push_back(edge(to,length,price));   //用邻接表表示无向图,所以得记录两次,一去一回
            graph[to].push_back(edge(from,length,price));
        }
        int s,t;
        cin>>s>>t;
        digkstra(s);
        cout<<dis[t]<<' '<<cost[t]<<endl;
    }
    return 0;
 
}

知识要点

  • memset和fill的用法,头文件是cstring
  • point和edge的结构体的定义
  • 图的定义是数组,元素为边的vector
  • INT_MAX的头文件为climits
  • 定义的优先队列,要记得在定义队列元素的时候重载操作符,规定优先级
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值