P4779 【dijkstra】+(堆优化)+(链式前向星) (模板题)

<题目链接>

题目描述

给定一个 N 个点, M 条有向边的带非负权图,请你计算从 S 出发,到每个点的距离。

数据保证你能从 S 出发到任意点。

输入格式:

第一行为三个正整数 N,M,S 。 第二行起 M 行,每行三个非负整数 ui, vi, wi,表示从 ui到 vi 有一条权值为 wi 的边。

输出格式:

输出一行 N 个空格分隔的非负整数,表示 S 到每个点的距离。

1<=N<=100000

1<=M<=200000

解题分析:

由于n和m的数据太大,所以这里不能够用普通的dijkstra算法,因为它的复杂度为O(n^2),所以我们这里要用的是复杂度为O(nlog(n))的加上堆优化的dijkstra算法,并且,下面的代码存图用的是链式前向星。

#include <bits/stdc++.h>
using namespace std;
const int M = 2e5 + 7;
const int ME = 2e5 + 7;
const int INF = 2147483647;
int head[M];      
int cnt, dis[M], n, m, vis[M];

struct EDGE
{
    int next; //上一条同起点的边在edge[]数组中的储存坐标
    int to;   //该边的终点
    int w;    //该边的权值
}edge[ME];


void addedge(int u, int to, int w) {     //链式前向星的构建
    edge[++cnt].to = to; edge[cnt].w = w; 
    edge[cnt].next = head[u];   //当前边的下一条边是输入的以u为顶点的上一条边 (next就相当于)
    head[u] = cnt;       //表示以u为起点的当前边在edge[]数组中的序号
}

struct node
{
    int dis, index;
    bool operator < (const node &k) const {       //重载排序
        return dis>k.dis;              //由于要保证dis小的优先,所以将dis从大到小排序 
    }
}d[M];

void dijkstra(int s) {
    for (int i = 1; i <= n; i++) vis[i] = 0, d[i].dis = INF, d[i].index = i;
    priority_queue<node> q;
    d[s].dis = 0; q.push(d[s]);

    while (!q.empty()) {
        int u = q.top().index;    //队列里此时距离起点最短的点
        q.pop();
        if (vis[u]) continue;
        vis[u] = 1;    

        for (int i = head[u]; ~i; i = edge[i].next) {         //链式前向星,以u为起点的所有线段的遍历方法(模板)
            int v = edge[i].to;
            if (d[v].dis>d[u].dis + edge[i].w) {          //更新以 u 为起点的,所有与它相连的线段的终点到s起点的最短距离            
                d[v].dis = d[u].dis + edge[i].w;
                q.push(d[v]);        //由于更新了d[v].dis,所以所有以d[v].index为起点的线段也要更新,所以将d[v]压入队列
            }
        }
    }
    return;
}

int main() {
    int s; cnt = 0;
    memset(head, -1, sizeof(head));
    scanf("%d%d%d", &n, &m, &s);
    for (int i = 1; i <= m; i++) {
        int u, to, w;
        scanf("%d%d%d", &u, &to, &w);
        addedge(u, to, w);
    }
    dijkstra(s);        //以s为起点

    for (int i = 1; i <= n; i++)        //学习这种代码风格
        printf("%d%s", d[i].dis, i == n ? " \n" : " ");
    return 0;
}

2018-08-13

猜你喜欢

转载自www.cnblogs.com/00isok/p/9470579.html