zoukankan      html  css  js  c++  java
  • 【BZOJ-4289】Tax 最短路 + 技巧建图(化边为点)

    题意

    给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大
    值,求从起点1到点N的最小代价。起点的代价是离开起点的边的边权,终点的代价是进入终
    点的边的边权
    N<=100000
    M<=200000

    题解一

    1. 无向图连边时要拆成两条边,这大家都知道
    2. 然后把边看成”点”,(优化:)因为不可能每个”点”之间都能连边,所以
    3. 对除了 1点和 n点之外的点连出去的边(真实边)按权值从小到大排个序,边看作”点”
    4. 然后 i “点”向 i + 1”点”连一条边值为(化点之前的两条边的权值差);i “点”向 i - 1”点”连一条权值为0LL的边;然后每个”点”和它反向边化成的”点”连一条边值为该边以前权值的边。
    5. 然后用堆优化的dij跑一遍最短路,求出dis[i]( dis[i] = 初始点 到 i “点”的最短距离)。
    6. 最短路初始过程:将原点1连出去的 边看成点 后,加入队列。
    7. 求值:枚举连向终点n的边,维护ans = minj{dis[i^1] + val[i]}// i 是边的编号

    题解二

    比较有技巧的建图

    首先考虑暴力点的建图:

    把每条无向边拆成两条有向边.把每条边看成一个点,对于两条边a->b,b->c

    在这两条边之间连有向边,边权为这两条边的权值的较大值.

    新建源点S,汇点T, S向所有从1连出去的边连边,所有指向n的边向T连边. 求S->T的最短路即可.

    这样的复杂度会达到O(m2)O(m2)

    考虑优化一下,有个类似网络流中补流思想的方法:

    考虑利用差值来建边.

    依然把每条边x-y拆成x->y,y->x.

    枚举每个中转点x. 将x的出边按权值排序,x的每条入边向对应的出边连该边权值的边,x的每条出边向第一个比它大的出边连两边权差值的边,x的每条出边向第一个比它小的出边连权值为0的边. 新建源汇S,T S向每条1的出边连权值为该边边权的边.每条n的入边向T连该边权值的边.

    跑S->T的最短路即可.

    这样的复杂度是O(mlogm)O(mlogm)就可以AC

    顺带提一句,用Dijkstra效率很快

    C++代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 7;
    
    struct Edge{
        int from,to;
        int w,nxt;
    }edge[maxn << 2],e[maxn << 2];
    
    int n , m ;
    int pre[maxn];
    int fa[maxn],cost[maxn],dep[maxn];
    int head[maxn],tot;
    
    void init(){
        tot = 0;
        memset(head,-1,sizeof head);
        for(int i = 1;i <= n ; i++){
            pre[i] = i;
        }
    }
    
    bool cmp(Edge a,Edge b){
        return a.w < b.w;
    }
    
    void add_edge(int u ,int v,int w){
        e[tot].from = u;
        e[tot].to = v;
        e[tot].w = w;
        e[tot].nxt = head[u];
        head[u] = tot ++;
    }
    
    inline int find(int x){if(x == pre[x])return x;else return pre[x] = find(pre[x]);}
    
    void kruskal(){
        sort(edge+1,edge+1+m,cmp);
        int fu,fv,u,v;
        for(int i = 1;i <= m; i++){
            u = edge[i].from;
            v = edge[i].to;
            fu = find(u);
            fv = find(v);
            if(fu != fv){
                pre[fu] = fv;
                add_edge(u,v,edge[i].w);
                add_edge(v,u,edge[i].w);
            }
        }
    }
    
    void dfs(int u,int Fa,int step){
        int v;
        for(int i = head[u]; ~i ;i = e[i].nxt){
            v = e[i].to;
            if(v ==Fa) continue;
            dep[v] = step;
            fa[v] = u;
            cost[v] = e[i].w;
            dfs(v,u,step + 1);
        }
    }
    
    int lca(int u,int v){
        int du = dep[u];
        int dv = dep[v];
        int res = 0;
        while(du > dv){
            res = max(res,cost[u]);
            u = fa[u];
            du --;
        }
        while(dv > du){
            res = max(res,cost[v]);
            v = fa[v];
            dv --;
        }
        while(u != v){
            res = max(res,cost[u]);
            res = max(res,cost[v]);
            u = fa[u];
            v = fa[v];
        }
        return res;
    }
    
    int main(){
        int cas = 0;
        while(cin >> n >> m){
            if(cas) puts("");
            else cas ++;
            init();
            for(int i = 1;i <= m; i ++){
                int u , v , w;
                cin >> u >> v >> w;
                edge[i].from = u;
                edge[i].to = v;
                edge[i].w = w;
            }
            //cout << 1 ;
            kruskal();
            fa[1] = cost[1] = dep[1] = 0;
            dfs(1,-1,1);
            int q;
            cin >> q;
            while(q--){
                int u , v ;
                cin >> u >> v;
            cout << lca(u,v) << endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    【设计模式】 五大原则
    RFC
    Linux虚拟服务器--LVS
    Git fast forward提交
    Fighting regressions with git bisect---within git bisect algorithm
    Git bare repo with multiple branches
    英特尔和Red Hat合作实现Gnome桌面的Wayland支持
    如何成为一个Linux内核开发者
    Terminal emulator
    bootstrap基础学习【网格系统】(三)
  • 原文地址:https://www.cnblogs.com/DWVictor/p/11271557.html
Copyright © 2011-2022 走看看