数据结构之最短路径Dijkdtra算法

题意:两个整数:T和N.接下来T行,每行描述以三个以空格分隔的整数的轨迹。 
前两个分别代表两个点,第三个为两点间的距离
输出:从N到1必须经过的最小距离 

<3> 优先队列优化的djk求单源最短路,链式前向星存图 时间复杂度o(E * log(V)) 

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std; 

typedef pair<int, int> pii;  //first存储权值,second存储终点 
const int N=1e5+10;  //最大点数
const int maxn=1e6+10;  //边的对数 
const int INF=0x3f3f3f3f;

int n,m;   //n是图中的点数,m是图中的边数
int head[N],top;  //head[i]:记录以i为起点的最后一条边  top:记录边的输入,每输入一组top++ 
int dis[N];    //dis[i]:存储点i到起点的最短距离 

void init(int n){ // 初始化
    memset(head, -1, sizeof(int) * (n + 1));
    top = 0;
}

struct Edge{   //边的定义
    int to,val,next;  //to:边的终点 val:权值 next:与该边同起点的上一条边的位置 
    Edge(){}
    Edge(int _to,int _val,int _next){
        to=_to; val=_val; next=_next;
    }
}edge[maxn<<1];  //!!如果是双向图的话,边的数量是题目中描述的二倍

void Add(int u,int v,int val){   //添加单向边
    edge[top]=Edge(v,val,head[u]);
    head[u]=top++;
}

void getmap(int m){  //构图 
    int u,v,val;
    while(m--){
        scanf("%d %d %d",&u,&v,&val);  //u->v有边
        Add(u,v,val);
        Add(v,u,val);   //如果是无向图,就加上这个代码
    }
}

void djk(int st,int ed){   //!!如果是双向图的话,边的数量是题目中描述的二倍
    memset(dis,0x3f,sizeof(int) *(n+1));
    priority_queue<pii,vector<pii>,greater<pii> > que;  //优先队列由小到大排序默认写法 
    dis[st]=0;   //起点到起点的距离为0
    que.push(make_pair(0,st));   //make_pair(dis, v) 表示v到起点的距离为dis
    while(!que.empty()){
        pii p=que.top();  //每次取离起点最近的
        que.pop();
        int v=p.second;   //v:边的终点 
        if(dis[v]<p.first) continue;  //如果没有更优,跳过
        for(int i=head[v];~i;i=edge[i].next){
            Edge e=edge[i];
            if(dis[e.to]>dis[v]+e.val){  //是否可以进行松弛
                dis[e.to] = dis[v] + e.val;
                que.push(make_pair(dis[e.to], e.to));
            } 
        }
    }
    printf("%d\n", dis[ed] == INF ? -1 : dis[ed]);
}

int main(){
    int t;
    scanf("%d %d",&t,&n);    //t为边数,n代表起点 
    init(n);
    getmap(t);
    djk(n,1);  //n:起点  1:终点
    return 0;
}

猜你喜欢

转载自blog.csdn.net/HPU_FRDHR/article/details/81671055
今日推荐