zoukankan      html  css  js  c++  java
  • Dijkstra算法+堆优化【模板】

    Dijkstra算法用于求解一个点到所有点的距离

    例子

    5 5 1(5个点 5条边 起点为1号节点)
    1 2 20(下面5行是5条边的起点、终点与权值)
    2 3 30
    3 4 20
    4 5 20
    1 5 100

    代码

    //原版Dijkstra
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int edges[10002][10002];
    int dist[10002];
    int visited[10002];
    #define inf 0x3f3f3f3f
    int n, m, s;
    void Dijkstra()
    {
        fill(dist, dist + n+1, inf);//dist数组初始化为inf
        dist[s] = 0;//将起点的dist设为0
        for (int i = 1; i <= n; i++)//因为从起点开始,所以执行n次
        {
            int u = -1, min = inf;
            for (int j = 1; j <= n; j++)//寻找最短边
            {
                if (!visited[j] && dist[j] < min)
                {
                    u = j; min = dist[j];
                }
            }
            if (u == -1)return;
            visited[u] = 1;//这里不能忘记
            for (int j = 1; j <= n; j++)
            {
                if (!visited[j])
                {
                    if (min + edges[u][j] < dist[j])
                        dist[j] = min + edges[u][j];
                }
            }
        }
    
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin >> n >> m >> s;
        fill(edges[0], edges[0] + 10002 * 10002, inf);//这种写法在数据量比较大的题目中是会爆内存的
        for (int i = 1; i <= m; i++)
        {
            int a, b,c;
            cin >> a >> b >> c;
            edges[a][b] = c;
        }
        Dijkstra();
        for (int i = 1; i <= n; i++)
            printf("%s%d", i == 1 ? "" : " ", dist[i]);
    }

    防止爆内存Dijkstra

    题目:https://www.luogu.com.cn/problem/P3371

    本题目数据量

     但是还是TLE………………

    于是使用vector储存图,详见代码

    代码

    //改进vector版Dijkstra
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    using namespace std;
    typedef pair<int, int> p;
    //这里最好使用typedef 定义一下下面再用,如果直接vector<pair<int,int>> edges[10002];在OJ编程通不过…………
    //priority_queue<pair<int, int> > qq; 
    // 注意在两个尖括号之间一定要留 空格,防止误判
    
    
    
    vector<p> edges[10002];
    long long dist[10002];
    int visited[10002];
    #define inf 0x3f3f3f3f
    int n, m, s;
    void Dijkstra()
    {
        fill(dist, dist + n+1, inf);
        dist[s] = 0;
        for (int i = 1; i <= n; i++)
        {
            int u = -1;
            long long min = inf;
            for (int j = 1; j <= n; j++)
            {
                if (!visited[j] && dist[j] < min)
                {
                    u = j; min = dist[j];
                }
            }
            if (u == -1)return;
            visited[u] = 1;
            for (int j = 0; j <edges[u].size(); j++)//在以u为起点的所有边中寻找
            {
                int vv = edges[u][j].first;//是这条边的终点
                if (!visited[vv])
                {
                    if (min + edges[u][j].second< dist[vv])
                        dist[vv] = min + edges[u][j].second;
                }
            }
        }
    
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin >> n >> m >> s;
        for (int i = 1; i <= m; i++)
        {
            int a, b, c;
            cin >> a >> b >> c;
            edges[a].push_back(make_pair(b, c));//使用每条边的起始节点作为edges的index,pair里是终点与权值
        }
        Dijkstra();
        bool space = false;
        for (int i = 1; i <= n; i++)
        {
            if (visited[i])
                printf("%s%d",space==false?"":" ", dist[i]);
            else printf("%s%s", space == false ? "" : " ", "2147483647");
            space = true;
        }
    }
    //测试实例
    //5 15 5
    //2 2 270
    //1 4 89
    //2 1 3
    //5 5 261
    //5 2 163
    //5 5 275
    //4 5 108
    //4 4 231
    //3 4 213
    //3 3 119
    //3 1 77
    //3 1 6
    //2 4 83
    //5 5 196
    //5 5 94
    
    //166 163 2147483647 246 0

    Dijkstra堆优化

    题目:https://www.luogu.com.cn/problem/P4779

    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define maxn 100010
    #define maxm 500010
    #define inf 0x7fffffff
    struct edge
    {
        int to;//终点
        int dis;//权值
        int next;//下一条边
        //不添加from起点,意义不大
    };
    struct node
    {
        int dis;//权值
        int pos;//下标
        bool operator <(const node &x)const
        {
            return x.dis < dis;//从小到大排序
        }
    };
    edge e[maxm];
    int head[maxn], dist[maxn], cnt, visited[maxn];
    int n, m, s; 
    priority_queue<node>q;//每次出队的都是dis最小的,节省了(更新后再比,出现更小的再更新此类情况)消耗的时间 
    void addedge(int u, int v, int w)
    {
        cnt++;
        e[cnt].dis = w;
        e[cnt].to = v;
        e[cnt].next = head[u];//head[u]总是临时存放着同起点的前一条边,当同起点的后一条边输入时,把前一条边的index赋值给这条边的next(于是同起点的边顺序是输入顺序的反序)
        head[u] = cnt;
    }
    void Dijkstra()
    {
        fill(dist, dist + n + 1, inf);    
        dist[s] = 0;
        q.push({ 0, s });//加入起点
        while (!q.empty())
        {
            node tmp = q.top();
            q.pop();
            int x = tmp.pos, d = tmp.dis;
            if (visited[x])continue;
            visited[x] = 1;//相当于前面的visited[u] = 1;
            for (int i = head[x]; i; i = e[i].next)
            {
                int y = e[i].to;
                if (dist[y] > dist[x] + e[i].dis)
                {
                    dist[y] = dist[x] + e[i].dis;
                        q.push({ dist[y], y });
                }
            }
        }
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin >> n >> m >> s;
        for (int i = 1; i <= m; i++)
        {
            int a, b, c;
            cin >> a >> b >> c;
            addedge(a, b, c);
        }
        Dijkstra();
        for (int i = 1; i <= n; i++)
            printf("%s%d", i == 1 ? "" : " ", dist[i]);
    }
  • 相关阅读:
    第九周学习总结&实验报告(7)
    团队展示
    结对编程
    微信公众号
    编程作业
    《构建之法》
    自我介绍
    java学期总结
    14周作业
    13周总结
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/12880897.html
Copyright © 2011-2022 走看看