找回密码
 立即注册
首页 业界区 业界 各种优化建图、最短路建模技巧

各种优化建图、最短路建模技巧

稼布欤 6 天前
直接看题吧,思路有了,但是有些题代码没打。兔子正在加油中。
优化建图

I.(线段树)CF786B Legacy

题目描述三种连边操作,执行 \(q(1\le n\le10^5)\) 次:

  • \(x\xrightarrow{w}y\)
  • \(x\xrightarrow{w}y,y\in[l,r]\)
  • \(x\xrightarrow{w}y,x\in[l,r]\)
求 \(s\) 到其余点的最短路。
暴力连边肯定不行。
有没有什么东西是把一个区间拆分成 \(\log\) 个的?
当然是线段树优化建图啦。因为加入的是一个区间,所以用线段树上的 \(\log\) 个结点来表示区间,对这些结点连边。
对于 \([l,r] \to v\),把 \(\log\) 个结点连向线段树上的 \(v\),之后把线段树本身连成一颗内向树。
对于 \([l,r] \gets v\),在对线段树内部连边时,显然不能和上一种情况连同一些结点,不然最短路都是 \(0\)。于是重新开一颗线段树,把这个颗树连成外向树。对于这颗线段树上的 \(\log\) 个结点,连向上内向树上的 \(v\)。
这两颗树上的叶子在原图上是同一个点,所以这两颗树的叶子要连权值为 \(0\) 的边(显然只需要外向树向内向树连边)。
对于建出来的图跑最短路,有 \(n\) 个结点 \(m\log n\) 条边,堆优化 Dijkstra 时间复杂度 \(\mathcal{O}(m\log_2 n)\)。
CF786B[code]#include#define int long long#define endl '\n'#define pi pairusing namespace std;const int N=3e6+10,K=5e5;int n, m, s, op, a[N], d[N];bool vis[N];priority_queue q;int pre[N], cnt;struct node{        int to, next, l;}g[N];void add(int u,int v,int l){        g[++cnt] = {v, pre, l};        pre = cnt;        return ;}struct Segment_Tree{#define ls (k > 1;            add(k, ls, 0);                add(k, rs, 0);            add(ls + K, k + K, 0);                add(rs + K, k + K, 0);            build(ls, l, mid);            build(rs, mid+1, r);        }        void modify(int k, int l, int r, int lx, int rx, int v, int w){            if(l >= lx && r > 1;            if(lx  mid) modify(rs, mid+1, r, lx, rx, v, w);            return ;        }}tree;inline void dijkstra(int s){    memset(d, 0x3f, sizeof d);        d = 0;    q.push(make_pair(0, s));    while(q.size()){        int x = q.top().second;                q.pop();        if(vis[x]) continue;        vis[x] = true;        for(int i = pre[x]; i; i = g.next){            int to = g.to, l = g.l;            if(d[to] > d[x] + l) {                                d[to] = d[x] + l;                                q.push(make_pair(-d[to], to));                        }        }    }    return ;}inline int read(){        int x;        cin >> x;        return x;}signed main(){        cin.tie(nullptr)->sync_with_stdio(false);        n = read(), m = read(), s = read();        tree.build(1, 1, n);    for(int i = 1; i
您需要登录后才可以回帖 登录 | 立即注册