Dijkstra seeking the shortest path Ⅱ | heap optimization sparse matrix optimization

Dijkstra seeking the shortest path Ⅱ | heap optimization sparse matrix optimization


from acwing850
Time limit:1s
Memory limit:64MB

Problem Description

Given a directed graph with n points and m edges, there may be multiple edges and self-loops in the graph, and all edge weights are non-negative.

Please find the shortest distance from point 1 to point n. If you cannot walk from point 1 to point n, output -1.

Input

The first line contains integers n and m.

Each of the next m rows contains three integers x, y, z, indicating that there is a directed edge from point x to point y, and the length of the side is z.

Output

Output an integer, representing the shortest distance from point 1 to point n.

If the path does not exist, -1 is output.

data range

1≤n,m≤1.5×10 5 ,1≤n,m≤1.5×10 5 , the
length of the sides involved in the figure is not less than 0 and not more than 10,000.

Sample Input

3 3
1 2 2
2 3 1
1 3 4

Sample Output

3

For this problem, compared with Dijkstra's shortest path Ⅰ , the amount of data has become larger, and the magnitude of the point edge has also changed. For the general shortest path problem, the edge is the square of the point magnitude, so the general amount of data is very small. A two-dimensional array can be created directly; but for a larger amount of data, when the edges and points are of the same magnitude, the memory is not enough to open up, then we need to use a sparse matrix, or a vector analog linked list (pointer). can.

(I’m going to be autistic here. I just learned about sparse matrices this semester. I almost forgot about it. I thought about it for a while, but I only used storage for this topic. Then I added a little bit of the idea of ​​search and collection for indexing)

Of course, the complexity of the traditional naive dijkstra algorithm is O(n^2). Here we use the priority queue to reduce the time complexity, and sort them according to the weight from small to large (greater), so that every element that pops up is not Among the marked points, the closest to 1 (starting point), this operation is equivalent to traversing 1 to n in dijkstra's naive method to find the minimum distance point.

AC code:

#include<cstdio>
#include<queue>
#include<cstring>
#define pii pair<int,int>
using namespace std;
int n,m;
int from[150005],father[150005],dis[150005],edge = 0;pii p[150005];
bool note[150005];
void init(){
    
    
    scanf("%d %d",&n,&m);
    memset(from,-1,sizeof(from));   //后续操作当遇到-1的时候结束dijsktra内部循环
    int f,t,w;
    while(m--){
    
    
        scanf("%d %d %d",&f,&t,&w);
        p[edge].first = w,p[edge].second = t,father[edge] = from[f],from[f] = edge++;
    }//这个步骤,是用pair存输入的边的终点(second)和边权(first)
     //father可以理解为并查集,对于所有起点相同的边,下一个位置,存着上一个的索引,而from是用来索引最后一个	   //father的,这里可以和并查集的查找函数联系起来理解
    for(int i = 2;i <= n;++i)
        dis[i] = 0x3f3f3f3f;
}
int main(){
    
    
    init();
    priority_queue<pii,vector<pii>,greater<pii> > q;
    q.push({
    
    0,1});          //优先队列,按边权从小到大排序,所以first存的是边权
    while(!q.empty()){
    
    
        pii x = q.top();q.pop();
        if(note[x.second])
            continue;
        note[x.second] = true;
        for(int i = from[x.second];i != -1;i = father[i])   //经典并查集思想了
            if(!note[p[i].second] && dis[p[i].second] > dis[x.second] + p[i].first)
                dis[p[i].second] = dis[x.second] + p[i].first,q.push({
    
    dis[p[i].second],p[i].second});//更新了就压入队列
    }
    if(dis[n] == 0x3f3f3f3f)
        printf("-1");
    else
        printf("%d",dis[n]);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45985728/article/details/113706624