zoukankan      html  css  js  c++  java
  • 最短路-Dijkstra算法整理

    维基说的很全面:https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

    理解:

      先设置访问数组vis[]和距离数组dist[],开始时把源点(source)先加入已访问数组(vis[source]=1),源点到源点的距离数组设为0(dist[source]=0);然后其它点到源点的dist[]为源点到该点的距离。然后找与源点相连的最近的点,并将其加入访问数组,再用这个点利用松弛操作更新其它未访问的点。循环执行顶点数-1次结束。

    下面代码假设源点为1,终点为N。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int maxn = 2000;
    int matrix[maxn][maxn];
    int vis[maxn], dist[maxn];
    int N, M;
    
    void Dijkstra(int source)
    {
        memset(vis, 0, sizeof(vis));
        vis[source] = 1;
        for (int i = 1; i <= N; i++) dist[i] = matrix[source][i];
    
        int cost, k;
        for (int i = 1; i < N; i++)
        {
            cost = INF;
            for (int j = 0; j <= N; j++)
            {
                if (!vis[j] && dist[j]<cost)
                {
                    cost = dist[j];
                    k = j;
                }
            }
    
            vis[k] = 1;
    
            for (int j = 0; j <= N; j++)
            {
                if (!vis[j] && matrix[k][j] != INF&&dist[j]>matrix[k][j] + cost)
                {
                    dist[j] = matrix[k][j] + cost;
                }
            }
    
        }
    }
    
    int main()
    {
        while (scanf("%d%d", &N, &M))
        {
            for (int i = 0; i <= N; i++)
                for (int j = 0; j <= N; j++)
                    if (i == j) matrix[i][j] = 0;
                    else matrix[i][j] = INF;
    
            for (int i = 0; i<M; i++) {
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                matrix[u][v] = matrix[v][u] = w;
            }
            Dijkstra(1);
            printf("%d
    ", dist[N]);
        }
        return 0;
    }

    用优先队列和vector:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=2000;
    struct Node
    {
        int num,dis;//num存储当前节点的编号,dis存储路径长度
        Node(){}
        Node(int a,int b){num=a;dis=b;}
        bool operator < (const Node& rhs)const{
            dis>rhs.dis;
        }
    };
    priority_queue<Node>que;
    vector<vector<Node> >v;
    int vis[maxn],dist[maxn];
    int N,M;
    
    void Dijkstra(int s)
    {
        for (int i=0;i<=N;i++) dist[i]=INF;
        dist[s]=0;
        que.push(Node(s,dist[s]));
        while(!que.empty())
        {
            Node p=que.top();que.pop();
            for (int i=0;i<v[p.num].size();i++)
            {
                Node q;
                q.num=v[p.num][i].num;
                if(dist[q.num]>dist[p.num]+v[p.num][i].dis)
                {
                    dist[q.num]=dist[p.num]+v[p.num][i].dis;
                    que.push(Node(q.num,dist[q.num]));
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d",&N,&M);
        v.clear();
        v.resize(N+1);
        for (int i=0;i<M;i++)
        {
            int fr,to,w;
            scanf("%d%d%d",&fr,&to,&w);
            v[fr].push_back(Node(to,w));
            v[to].push_back(Node(fr,w));
    
        }
        Dijkstra(1);
        printf("%d
    ",dist[N]);
    }

     以hdu1874畅通工程续为例,一个pair较为偷懒的写法:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 const int maxn = 1005;
     7 vector<pair<int, int> > E[maxn];
     8 int d[maxn];
     9 int n, m;
    10 
    11 void Dijkstra(int s)
    12 {
    13     priority_queue<pair<int, int> >Q;
    14     d[s] = 0;
    15     Q.push(make_pair(-d[s],s));
    16     while (!Q.empty())
    17     {
    18         int now = Q.top().second; Q.pop();
    19         for (int i = 0; i < E[now].size(); i++)
    20         {
    21             int v = E[now][i].first;
    22             if (d[v] > d[now] + E[now][i].second)
    23             {
    24                 d[v] = d[now] + E[now][i].second;
    25                 Q.push(make_pair(-d[v], v));
    26             }
    27         }
    28     }
    29 }
    30 
    31 int main()
    32 {
    33     while (scanf("%d%d",&n,&m)==2)
    34     {
    35         for (int i = 0; i < n; i++) E[i].clear();
    36         for (int i = 0; i < n; i++) d[i] = 1e9;
    37         for (int i = 0; i < m; i++)
    38         {
    39             int x, y, z;
    40             scanf("%d%d%d", &x, &y, &z);
    41             E[x].push_back(make_pair(y,z));
    42             E[y].push_back(make_pair(x, z));
    43         }
    44         int s, t;
    45         scanf("%d%d", &s, &t);
    46         Dijkstra(s);
    47         if (d[t] == 1e9)
    48             printf("-1
    ");
    49         else
    50             printf("%d
    ", d[t]);
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    技术专题:ROS通过TTL值来防止二层路由的最简单办法
    唉,一大早起床遇到脑残的,实在无语!QQ:124316912
    简单描述FTTH方案中EPON、GPON设置的优势、原理及城中村的解决方案
    9.9成新WAYOS、HZZ、ROS软件路由WAN扩展交换机大量到货只需450
    辅助工具:免输入命令,WAYOS通过交换机一键扩展WAN口工具
    配置文档:3COM 4200 3C17300A配置文件,可与WAYOS、ROS、海蜘蛛多WAN对接
    网站页面跳转代码大全,网站网页跳转代码
    popupWin 属性及用法介绍 ASP.NET控件,仿QQ,msn右下角弹出窗口
    IIS打开ASP文件出现Server Application Error提示的解决方法,本人亲历,成功
    教你学会提高无线网下载速度的方法
  • 原文地址:https://www.cnblogs.com/zxhyxiao/p/7223886.html
Copyright © 2011-2022 走看看