• luogu解题报告:P1186玛丽卡【图论/最短路/堆优化dijkstra】


    题目见https://www.luogu.org/problem/show?pid=1186

    分析

    一个简单的思路是枚举删除每一条边,然后跑堆优化dijkstra算法。但这样的复杂度恐怕过大。因此有一个简单的优化思路:第一次跑dijkstra时记录路径上的点。显然,堵车的路一定处于这些点之间,因为如果不是,玛丽卡走原先的最短路一定最短。因此只需要枚举删除处于最短路上的点之间的边,再跑堆优化dijkstra即可。代码使用zkw树优化。

    示例代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    // basic of graph
    struct p {
        int to, next, dis;
    }edge[3000000];
    int head[1005], top = 0;
    void push(int i, int j, int k)
    {
        edge[++top].to = j;
        edge[top].dis  = k;
        edge[top].next = head[i];
        head[i] = top;
    }
    
    // a heap
    
    class zkw_tree {
        int dat[2050];
        int from[2050];
        int n;
        public:
            zkw_tree()
            {
                memset(dat, 127/3, sizeof dat);
                for (int i = 1; i < 2050; i++)
                    from[i] = i-n+1;
            }
            void clear()
            {
                memset(dat, 127/3, sizeof dat);
                for (int i = 1; i < 2050; i++)
                    from[i] = i-n+1;
            }
            void init(int num)
            {
                n = num;
            }
            void modify(int i, int new_val)
            {
                dat[i+n-1] = new_val;
                for (int pos = (i+n-1)>>1; pos; pos>>=1) {
                    int lft = pos<<1, rgt = (pos<<1)+1;
                    if (dat[lft] <= dat[rgt]) {
                        dat[pos] = dat[lft];
                        from[pos] = from[lft];
                    } else {
                        dat[pos] = dat[rgt];
                        from[pos] = from[rgt];
                    }
                }
            }
            int query()
            {
                return from[1];
            }
            int top()
            {
                return dat[1];
            }
    }zkw_heap;
    
    // some var & func
    int forbid_s = 0, forbid_t = 0;
    int n, m;
    bool eq(int a, int b, int c, int d)
    {
        return (a == c && b == d) || (a == d && b == c);
    }
    
    // dijkstra
    int dis[1005], pre[1005];
    int dijkstra(bool take_path = false)
    {
        memset(dis, 127/3, sizeof dis);
        dis[1] = 0;
        zkw_heap.clear();
        zkw_heap.modify(1, 0);
        for (int i = 1; i < n; i++) {
            int k = zkw_heap.query();
            dis[k] = zkw_heap.top(); zkw_heap.modify(k, 233333333);
            //cout << k << " " << dis[k] << endl;
            if (k == n) break;
            for (int j = head[k]; j; j = edge[j].next) {
                int to = edge[j].to, d = edge[j].dis;
                if (dis[to] > dis[k]+d && !eq(k, to, forbid_s, forbid_t)) {
                    dis[to] = dis[k]+d;
                    if (take_path)
                        pre[to] = k;
                    zkw_heap.modify(to, dis[to]);
                }
            }
        }
        return dis[n];
    }
  • 相关阅读:
    mysql 索引
    springboot + maven jar打包和linux部署
    个人项目———Java实现WordCount
    第四周助教观察记录
    第三周助教工作观察记录
    2019年春-软件工程原理与方法-助教总结
    第十五周助教小结
    第十一周助教小结
    团队作业-设计 成绩汇总
    团队作业选题及需求分析成绩汇总
  • 原文地址:https://www.cnblogs.com/ljt12138/p/6684366.html
Copyright © 2020-2023  润新知