HDU3790 最短路径问题+dij算法

最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 25261    Accepted Submission(s): 7538


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

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

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

Sample Input
  
  
3 2 1 2 5 6 2 3 4 5 1 3 0 0
 

Sample Output
  
  
9 11
 

Source
 

Recommend
notonlysuccess   |   We have carefully selected several similar problems for you:   2544  1874  2066  1217  2112 


解题思路:

直接dij算,只不过当最短路长度一样的时候选择花费最小的那个就好了。


#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 10005 ;
const int INF = 0x3f3f3f3f ;
int n,m ;
struct Edge{
    int from;
    int to ;
    int dist ;
    int p ;
};
struct node{
    int u,d ;
    bool operator <(const node &p)const{
        return d>p.d ;
    }
};
vector<Edge> edges ;
vector<int>G[maxn] ;
bool done[maxn] ;
int d[maxn] ;
int pp[maxn] ;
void addEdge(int from,int to,int d,int p){
    edges.push_back((Edge){from,to,d,p}) ;
    int mm = edges.size() ;
    G[from].push_back(mm-1) ;
}
void dij01(int s){
    priority_queue<node>qq ;
    for(int i=0;i<n;i++){d[i]=INF,pp[i]=INF ;}
    d[s]=0 ;
    pp[s]=0 ;
    memset(done,false,sizeof(done)) ;
    qq.push((node){s,0}) ;
    while(!qq.empty()){
        node x = qq.top() ;
        //cout<<"qq=="<<x.u<<" "<<x.d<<endl ;
        qq.pop() ;
        int u = x.u ;
        if(done[u])continue ;
        done[u]=true ;
        int len = G[u].size() ;
        for(int i=0;i<len;i++){
            Edge& e = edges[G[u][i]] ;
            //printf("i=%d\n",i);
            if(d[e.to]==d[u]+e.dist&&pp[e.to] > pp[u]+e.p){
                pp[e.to] = pp[u]+e.p ;
            }
            if(d[e.to]>d[u]+e.dist){
                d[e.to] = d[u]+e.dist ;
                pp[e.to] = pp[u]+e.p ;
                qq.push((node){e.to,d[e.to]}) ;
            }
        }
    }
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        edges.clear() ;
        for(int i=0;i<n;i++)G[i].clear();
        if(n+m==0)break ;
        for(int i=0;i<m;i++){
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d) ;
            //cin>>a>>b>>c>>d ;
            a--;
            b--;
            addEdge(a,b,c,d) ;
            addEdge(b,a,c,d) ;
        }
        int s,t ;
        //cin>>s>>t ;
        scanf("%d%d",&s,&t);
        s-- ;
        t--;
        dij01(s) ;
        //cout<<d[t]<<" "<<pp[t]<<endl ;
        printf("%d %d\n",d[t],pp[t]);
    }
    return 0;
}
/**
3 3
1 2 5 6
2 3 4 5
1 3 9 10
1 3
0 0

*/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值