HDU -- 3790 最短路径问题 (Dijkstra+priority_queue)

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

思路分析:这是我做的第一道最短路径的题,但是还比较顺利,这道题没有涉及环路,所以设立一个dis[]数组,表示源点到各个点的距离,把源点s加入队列,则dis[s]=0,然后不断找出距离原点最近的点,利用这条边去更新扩展最短路径。因为这道题的限制条件不光是最短路径最短,还要保证有多个最短路径的情况下输出花费费用最短的,所以一方面在利用优先队列排顺序是要注意排序顺序,另一方面就是在单个元素的最短路径中,进入队列的判断是小于符号,这样从源点到这个点长度相同的其他最短路径就不会进入队列中,而这道题有两个因素考虑时就利用小于等于的符号,把从源点到这个点长度相同的最短路径都加到队列里,用队列去选择条花费最少的最短路径。

代码实现:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1010;
int visit[maxn],n,m,s,t;
struct Node{
    int num,d,p;
    Node(int nn=0,int dd=0,int pp=0):num(nn),d(dd),p(pp){}
}dis[maxn],w[maxn][maxn];
bool operator<(Node a,Node b){
    return (a.d==b.d)?a.p>b.p:a.d>b.d;
}
priority_queue<Node>Q;
void Dijkstra(){
    memset(visit,0,sizeof(visit));
    for(int i=1;i<=n;i++){
        dis[i].d=1e9;
        dis[i].p=1e9;
    }
    while(!Q.empty()) Q.pop();
    dis[s].d=0;
    dis[s].p=0;
    Node head(s,0,0);
    Q.push(head);
    while(!Q.empty()){
        head=Q.top();
        Q.pop();
        //printf("**%d\n",head.num);
        if(head.num==t){
            printf("%d %d\n",head.d,head.p);
            return;
        }
        visit[head.num]=1;
        for(int j=1;j<=n;j++){
            if(!visit[j]&&(dis[head.num].d+w[head.num][j].d<=dis[j].d)){
                dis[j].d=dis[head.num].d+w[head.num][j].d;
                dis[j].p=dis[head.num].p+w[head.num][j].p;
                Node next(j,dis[j].d,dis[j].p);
                Q.push(next);
            }
        }
    }
}
int main(){
    while(~scanf("%d%d",&n,&m),(n||m)){
        int a,b,c,d;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++){
                w[i][j].d=1e9;
                w[i][j].p=1e9;
            }
        }
        while(m--){
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(c<w[a][b].d||(c==w[a][b].d&&d<w[a][b].p)){
                w[a][b].d=w[b][a].d=c;
                w[a][b].p=w[b][a].p=d;
            }
        }
        scanf("%d%d",&s,&t);
        Dijkstra();
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值