zoukankan      html  css  js  c++  java
  • Solution -「Gym 102759F」Interval Graph

    (mathcal{Description})

      Link.

      给定 (n) 个区间,第 (i) 个为 ([l_i,r_i]),有权值 (w_i)。设一无向图 (G=(V={1,2,dots,n},E))((u,v)in ELeftrightarrow [l_u,r_u]cap[l_v,r_v] ot=varnothing),求删除若干区间使得 (G) 无环的被删除区间权值和的最小值。

      (nle2.5 imes10^5)

    (mathcal{Solution})

      不要学了 DP 就只想 DP,优化不来麻烦推翻重来。

      首先 (G) 的合法条件等价于不存在三区间交于一点,这是一个经典费用流流模型,建图方法略。

      当然直接 Dinic 啥的直接挂掉,考虑到只需要增广两次,可以使用势能 Dijkstra + EK 算法求最小费用最大流。概括上来说,令 (u) 的势能 (h_u) 为累加的 (d_u) 之和,使得此时图上 (w(u,v)+h_u-h_v) 非负,就能跑 Dijkstra 了。本题只用增广两次,所以在初始 DAG 上求出 (h) 后甚至不必更新。

      具体讲解:OneInDark %%%.

    (mathcal{Code})

    /*~Rainybunny~*/
    
    #include <queue>
    #include <cstdio>
    #include <iostream>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    typedef long long LL;
    typedef std::pair<LL, int> PLI;
    #define fi first
    #define se second
    
    template<typename Tp>
    inline Tp tmin( const Tp& a, const Tp& b ) { return a < b ? a : b; }
    
    const int MAXN = 2.5e5, MAXV = 5e5;
    const LL LINF = 1ll << 60;
    int n, ecnt = 1, mxp, head[MAXV + 5];
    struct Edge { int to, flw; LL cst; int nxt; } graph[( MAXV + MAXN ) * 2 + 5];
    LL hgt[MAXV + 5], dis[MAXV + 5];
    int pre[MAXV + 5], flw[MAXV + 5];
    
    inline void link( const int s, const int t, const int f, const LL c ) {
        graph[++ecnt] = { t, f, c, head[s] }, head[s] = ecnt;
        graph[++ecnt] = { s, 0, -c, head[t] }, head[t] = ecnt;
    }
    
    inline void getHeight() {
        hgt[0] = 0;
        rep ( u, 0, mxp - 1 ) {
            for ( int i = head[u]; i; i = graph[i].nxt ) if ( graph[i].flw ) {
                hgt[graph[i].to] = tmin( hgt[graph[i].to], hgt[u] + graph[i].cst );
            }
        }
    }
    
    inline bool dijkstra() {
        static bool vis[MAXV + 5];
        static std::priority_queue<PLI, std::vector<PLI>, std::greater<PLI> > heap;
        rep ( i, 0, mxp ) pre[i] = flw[i] = 0, dis[i] = LINF, vis[i] = false;
    
        heap.push( { dis[0] = 0, 0 } ), flw[0] = 2;
        while ( !heap.empty() ) {
            PLI p( heap.top() ); heap.pop();
            if ( vis[p.se] ) continue;
            vis[p.se] = true;
            
            for ( int i = head[p.se], v; i; i = graph[i].nxt ) {
                LL d = p.fi + graph[i].cst + hgt[p.se] - hgt[v = graph[i].to];
                if ( graph[i].flw && dis[v] > d ) {
                    heap.push( { dis[v] = d, v } );
                    pre[v] = i, flw[v] = tmin( flw[p.se], graph[i].flw );
                }
            }
        }
        return dis[mxp] != LINF;
    }
    
    int main() {
        std::ios::sync_with_stdio( false ), std::cin.tie( 0 );
    
        std::cin >> n;
        rep ( i, 1, n ) {
            int s, e; LL w; std::cin >> s >> e >> w, ++e;
            link( s, e, 1, -w ), mxp = mxp < e ? e : mxp;
        }
        rep ( i, 0, mxp - 1 ) link( i, i + 1, 2, 0 );
    
        getHeight();
        LL ans = 0;
        while ( dijkstra() ) {
            for ( int u = mxp; u; u = graph[pre[u] ^ 1].to ) {
                graph[pre[u]].flw -= flw[mxp], graph[pre[u] ^ 1].flw += flw[mxp];
            }
            ans += ( dis[mxp] + hgt[mxp] - hgt[0] ) * flw[mxp];
        }
    
        std::cout << -ans << '
    ';
        return 0;
    }
    
    
  • 相关阅读:
    【读书笔记】MSDN 上关于加密解密的一个例子
    【读书笔记】创建泛型编程类 由链表而深入
    HDFS数据加密空间Encryption zone
    各种数据库的连接方法
    Java基础5
    Java基础4
    Java基础2
    博客优化、收录、RSS技巧
    Java基础3
    Java基础8
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15145386.html
Copyright © 2011-2022 走看看