Solution -「Gym 102759F」Interval Graph
阿新 • • 發佈:2021-08-16
\(\mathcal{Description}\)
Link.
給定 \(n\) 個區間,第 \(i\) 個為 \([l_i,r_i]\),有權值 \(w_i\)。設一無向圖 \(G=(V=\{1,2,\dots,n\},E)\),\((u,v)\in E\Leftrightarrow [l_u,r_u]\cap[l_v,r_v]\not=\varnothing\),求刪除若干區間使得 \(G\) 無環的被刪除區間權值和的最小值。
\(n\le2.5\times10^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 << '\n'; return 0; }