• P2685 [TJOI2012]桥


    P2685 [TJOI2012]桥 

    思路:

    先求出最短路: d1[u] : u 到 1 的最短路, d2[u] : u 到 n 的最短路

    再求出一条从 1 到 n 的最短路链,然后从链上的每一个点出发dfs, 求出:

    l[u] : u 到 1 的最短路径过中和链的交点(离 1 最近的)

    r[u] : u 到 n 的最短路径过中和链的交点(离 n 最近的)

    然后对于一条非链上的边( u  ->  v ),边权为 w ,对于链上的 l[u] 到 r[v] 之间的边任意删一条边,

    最短路都有可能变成 d1[u] + w + d2[v] 然后在链上维护这个的最小值,就能知道删掉链上的每条边对最短路的影响

    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    using namespace std;
    #define y1 y11
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    //#define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pli pair<LL, int>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define pdd pair<double, double>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define debug(x) cerr << #x << " = " << x << "
    ";
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    //head
    
    const int N = 1e5 + 5;
    const int INF = 0x3f3f3f3f;
    int n, m, u, v, w, tot, d1[N], d2[N], link[N], id[N], l[N], r[N], a[N];
    int head[N], cnt = 0;
    bool vis[N*2];
    struct edge {
        int to, w, nxt;
    }edge[N*4];
    void add(int u, int v, int w) {
        edge[++cnt] = {v, w, head[u]};
        head[u] = cnt;
    }
    priority_queue<pii, vector<pii>, greater<pii> > q;
    int tree[N<<2], lazy[N<<2];
    void push_up(int rt) {
        tree[rt] = min(tree[rt<<1], tree[rt<<1|1]);
    }
    void push_down(int rt) {
        tree[rt<<1] = min(tree[rt<<1], lazy[rt]);
        tree[rt<<1|1] = min(tree[rt<<1|1], lazy[rt]);
        lazy[rt<<1] = min(lazy[rt<<1], lazy[rt]);
        lazy[rt<<1|1] = min(lazy[rt<<1|1], lazy[rt]);
        lazy[rt] = INF;
    }
    void build(int rt, int l, int r) {
        lazy[rt] = INF;
        if(l == r) {
            tree[rt] = INF;
            return ;
        }
        int m = l+r >> 1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    void down(int rt, int l, int r) {
        if(l == r) {
            a[l] = tree[rt];
            return ;
        }
        if(lazy[rt] != INF) push_down(rt);
        int m = l+r >> 1;
        down(ls);
        down(rs);
        push_up(rt);
    }
    void update(int L, int R, int x, int rt, int l, int r) {
        if(L <= l && r <= R) {
            tree[rt] = min(tree[rt], x);
            lazy[rt] = min(lazy[rt], x);
            return ;
        }
        if(lazy[rt] != INF) push_down(rt);
        int m = l+r >> 1;
        if(L <= m) update(L, R, x, ls);
        if(R > m) update(L, R, x, rs);
        push_up(rt);
    }
    
    void Dijkstra(int s, int *d) {
        for (int i = 1; i <= n; ++i) d[i] = INF;
        d[s] = 0;
        q.push({0, s});
        while(!q.empty()) {
            pii p = q.top();
            q.pop();
            int u = p.se;
            if(d[u] < p.fi) continue;
            for (int i = head[u]; i; i = edge[i].nxt) {
                int v = edge[i].to;
                int w = edge[i].w;
                if(d[v] > p.fi + w) {
                    d[v] = p.fi + w;
                    q.push({d[v], v});
                }
            }
        }
    }
    void dfs(int u, int s, int *bl, int *d) {
        bl[u] = s;
        for (int i = head[u]; i; i = edge[i].nxt) {
            int v = edge[i].to;
            int w = edge[i].w;
            //if(vis[(i+1)/2]) continue;
            if(bl[v] == 0 && id[v] == 0 && d[u] + w == d[v]) dfs(v, s, bl, d);
        }
    }
    int main() {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%d %d %d", &u, &v, &w);
            add(u, v, w);
            add(v, u, w);
        }
        Dijkstra(1, d1);
        Dijkstra(n, d2);
        tot = 0;
        u = 1;
        while(u != n) {
            link[++tot] = u;
            id[u] = tot;
            for (int i = head[u]; i; i = edge[i].nxt) {
                int v = edge[i].to;
                int w = edge[i].w;
                if(d2[v] + w == d2[u]){
                    vis[(i+1)/2] = true;
                    u = v;
                    break;
                }
            }
        }
        link[++tot] = n;
        id[n] = tot;
        for (int i = 1; i <= tot; ++i) dfs(link[i], link[i], l, d1);
        for (int i = tot; i >= 1; --i) dfs(link[i], link[i], r, d2);
        build(1, 1, tot-1);
        for (int u = 1; u <= n; ++u) {
            for (int i = head[u]; i; i = edge[i].nxt) {
                int v = edge[i].to;
                int w = edge[i].w;
                if(!vis[(i+1)/2]) {
                    if(id[l[u]] < id[r[v]]) update(id[l[u]], id[r[v]]-1, d1[u] + w + d2[v], 1, 1, tot-1);
                }
            }
        }
        down(1, 1, tot-1);
        int ans = 0, cnt = 0;
        for (int i = 1; i < tot; ++i) {
            if(a[i] > ans) {
                ans = a[i];
                cnt = 1;
            }
            else if(a[i] == ans) {
                cnt++;
            }
        }
        if(ans == d1[n]) cnt = m;
        printf("%d %d
    ", ans, cnt);
        return 0;
    }
  • 相关阅读:
    大道至简第四章读后感
    JAVA类与对象
    大道至简第三章读后感
    JAVA语法基础 动手动脑及课后作业
    课程作业01
    大道至简第二章读后感
    大道至简第一章读后感
    swift学习笔记之-自动引用计数
    swift学习笔记之-继承
    swift学习笔记之-闭包
  • 原文地址:https://www.cnblogs.com/widsom/p/10599870.html
Copyright © 2020-2023  润新知