博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P3358 最长k可重区间集问题
阅读量:7028 次
发布时间:2019-06-28

本文共 2553 字,大约阅读时间需要 8 分钟。

这题的写法非常巧妙。

每个位置的点向它的下一个位置连一个容量为\(INF\)的边,从区间的左端点往右端点拉一条容量为\(1\),费用为区间长度的边,从起点向点\(1\)连一条容量为\(k\)的边,限制只能流\(k\)次。这个建模的巧妙之处就在,它并没有明面上限制某个点最多经过\(k\)次,却实际上使路径单向,从而每一次流过都最多经过每个点一次,同时也并不会对并没有相交的区间造成影响。

#include 
using namespace std;const int N = 100010;const int M = 400010;const int INF = 0x3f3f3f3f;int n, k, tot, l[N], r[N], len[N], pos[N];int cnt = -1, head[N];struct edge { int nxt, to, w, f;}e[M];void add_edge (int from, int to, int flw, int val) { e[++cnt].nxt = head[from]; e[cnt].to = to; e[cnt].w = val; e[cnt].f = flw; head[from] = cnt;}void add_len (int u, int v, int f, int w) { add_edge (u, v, f, +w); add_edge (v, u, 0, -w);}void discretize () { for (int i = 1; i <= n; ++i) { cin >> l[i] >> r[i]; len[i] = r[i] - l[i]; pos[i * 2 - 1] = l[i], pos[i * 2] = r[i]; } sort (pos + 1, pos + 1 + n * 2); tot = unique (pos + 1, pos + 1 + n * 2) - pos - 1; for (int i = 1; i <= n; ++i) { l[i] = lower_bound (pos + 1, pos + 1 + tot, l[i]) - pos; r[i] = lower_bound (pos + 1, pos + 1 + tot, r[i]) - pos; }}queue
q;int dis[N], vis[N], flow[N];int pre_node[N], pre_edge[N];int spfa (int s, int t) { memset (vis, 0, sizeof (vis)); memset (dis, -0x3f, sizeof (dis)); memset (flow, 0x3f, sizeof (flow)); q.push (s); vis[s] = true; dis[s] = 0; while (!q.empty ()) { int u = q.front (); q.pop (); for (int i = head[u]; ~i; i = e[i].nxt) { int v = e[i].to; if (dis[v] < dis[u] + e[i].w && e[i].f) { dis[v] = dis[u] + e[i].w; flow[v] = min (flow[u], e[i].f); pre_edge[v] = i; pre_node[v] = u; if (!vis[v]) { vis[v] = true; q.push (v); } } } vis[u] = false; } return dis[t] != dis[0];}int main () { memset (head, -1, sizeof (head)); cin >> n >> k; discretize (); int s = tot + 1, t = tot + 2; add_len (s, 1, k, 0); add_len (tot, t, k, 0); for (int i = 1; i < tot; ++i) { add_len (i, i + 1, INF, 0); } for (int i = 1; i <= n; ++i) { add_len (l[i], r[i], 1, len[i]); } int max_cost = 0; while (spfa (s, t)) { max_cost += dis[t] * flow[t]; int u = t; while (u != s) { e[pre_edge[u] ^ 0].f -= flow[t]; e[pre_edge[u] ^ 1].f += flow[t]; u = pre_node[u]; } } cout << max_cost << endl;}

转载于:https://www.cnblogs.com/maomao9173/p/10478144.html

你可能感兴趣的文章
html基础之 input:type
查看>>
json-lib简单处理json和对json的简单介绍
查看>>
SQL学习之用通配符进行数据过滤
查看>>
jquery checkbox选中、改变状态、change和click事件
查看>>
java joor 实现反射简单调用
查看>>
membership与成员资格
查看>>
Guava 8-区间
查看>>
自定义Spark Partitioner提升es-hadoop Bulk效率
查看>>
总结一些机器视觉库
查看>>
window 后台执行 redis(隐藏窗口)
查看>>
How to print 如何输出 int64_t,uint64_t的值 in C
查看>>
在CentOS Linux下部署Activemq 5
查看>>
并发读写缓存实现机制:高并发下数据写入与过期
查看>>
BeanUtils.copyProperties()方法和PropertyUtils.copyProperties()的区别
查看>>
Atitit 发帖机系列(7) 词法分析的方法attilax大总结)
查看>>
NK3C开发要点
查看>>
Nexus私服使Maven更加强大
查看>>
wireless tool 移植
查看>>
sp_MSforeachtable使用方法
查看>>
D django 用户认证系统
查看>>