Solution -「Gym 102759F」Interval Graph
Link.
给定 个区间,第 个为 ,有权值 。设一无向图 ,,求删除若干区间使得 无环的被删除区间权值和的最小值。
。
不要学了 DP 就只想 DP,优化不来麻烦推翻重来。
首先 的合法条件等价于不存在三区间交于一点,这是一个经典费用流流模型,建图方法略。
当然直接 Dinic 啥的直接挂掉,考虑到只需要增广两次,可以使用势能 Dijkstra + EK 算法求最小费用最大流。概括上来说,令 的势能 为累加的 之和,使得此时图上 非负,就能跑 Dijkstra 了。本题只用增广两次,所以在初始 DAG 上求出 后甚至不必更新。
具体讲解:OneInDark %%%.
/*~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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现