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;
    }
    
    
  • 相关阅读:
    三数之和
    罗马数字与整数
    Oracle 开启或关闭归档
    Oracle RMAN scripts to delete archivelog
    Oracle check TBS usage
    Oracle kill locked sessions
    场景9 深入RAC运行原理
    场景7 Data Guard
    场景4 Data Warehouse Management 数据仓库
    场景5 Performance Management
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15145386.html
Copyright © 2011-2022 走看看