LOJ6014「网络流 24 题 - 15」最长 k 可重区间集 坠大权不相交路径 坠大费用坠大流
2017-12-08 09:11
405 查看
大家都很强, 可与之共勉 。
题意:给定实直线L上n个开区间组成的集合I,和一个正整数k,试设计一个算法,从开区间集合I中选取出开区间集合 S⊆I,使得在实直线L的任何一点x, S中包含点x的开区间个数不超过k。且 ∑z∈S|z|达到最大。这样的集合S称为开区间集合I的最长 k可重区间集。∑z∈S|z|称为最长k可重区间集的长度。
对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度。
题解:
把答案看作是k条路径的权值和坠大,路径不存在边相交(此处的边就是区间)。
既然是点可以重合,那么可以不拆点(其实拆点也可以的)。
因为是k条路径,所以从源点到一号点连一条容量为k,费用为0的边。最后一个点向汇点,连一条容量为x(x∈[k,+∞)),的边,之后对于lr,ri之间连一条容量为1,费用为长度的边。然后我们要保证可以有区间不被选到(跳过这个区间),每个点向下一个点连一条容量为+∞(其实大于等于k就够了),然后直接跑最大费用最大流。最后一定满足条件。最后的最大流一定是k。
画画图很好理解的
# include <bits/stdc++.h> template < class T > inline bool chkmax ( T& d, const T& x ) { return d < x ? ( d = x ), 1 : 0 ; } template < class T > inline bool chkmin ( T& d, const T& x ) { return d > x ? ( d = x ), 1 : 0 ; } # define oo 0x3f3f3f3f # define N 1050 # define M 5050 class MaxCostMaxFlow { private : struct edge { int to, nxt, w, cost ; } g [M << 1] ; int S, T ; int head , dis , pre , ecnt ; inline bool spfa ( int S, int T ) { static std :: bitset < N > inq ; static std :: deque < int > Q ; inq.reset ( ) ; Q.clear ( ) ; memset ( pre, 0, sizeof ( int ) * ( T + 1 ) ) ; memset ( dis, -1, sizeof ( int ) * ( T + 1 ) ) ; Q.push_front ( S ) ; inq [S] = 1 ; dis [S] = 0x3f3f3f3f ; while ( ! Q.empty ( ) ) { int u = Q.front ( ) ; Q.pop_front ( ) ; inq [u] = 0 ; for ( int i = head [u] ; i ; i = g [i].nxt ) { int& v = g [i].to ; if ( g [i].w && chkmax ( dis [v], dis [u] + g [i].cost ) ) { pre [v] = i ; if ( ! inq [v] ) { ( Q.empty ( ) || dis [v] > dis [Q.front ( )] ) ? Q.push_front ( v ) : Q.push_back ( v ) ; inq [v] = 1 ; } } } } return ( bool ) pre [T] ; } public : MaxCostMaxFlow ( ) { ecnt = 1 ; memset ( head, 0, sizeof head ) ; } inline void clear ( ) { ecnt = 1 ; memset ( head, 0, sizeof head ) ; } inline void add_edge ( int u, int v, int w, int cost ) { g [++ ecnt] = ( edge ) { v, head [u], w, cost } ; head [u] = ecnt ; g [++ ecnt] = ( edge ) { u, head [v], 0, -cost } ; head [v] = ecnt ; } std :: pair < int, int > mcmf ( int S, int T ) { this -> S = S, this -> T = T ; int flow = 0, cost = 0, x ; while ( spfa ( S, T ) ) { x = oo ; for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) chkmin ( x, g [i].w ) ; for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) { g [i].w -= x, g [i ^ 1].w += x ; cost += x * g [i].cost ; } flow += x ; } return std :: make_pair ( flow, cost ) ; } } Lazer ; int dust ; int l , r , val ; # undef N # undef M int main ( ) { int n, k ; scanf ( "%d%d", & n, & k ) ; const int S = 2 * n + 1, T = 2 * n + 2 ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d%d", l + i, r + i ) ; if ( l [i] > r [i] ) std :: swap ( l [i], r [i] ) ; dust [( i << 1 ) - 1] = l [i], dust [i << 1] = r [i] ; val [i] = ( r [i] - l [i] ) ; } std :: sort ( dust + 1, dust + n + n + 1 ) ; for ( int i = 1 ; i <= n ; ++ i ) { l [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, l [i] ) - dust ; r [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, r [i] ) - dust ; } Lazer.add_edge ( S, 1, k, 0 ), Lazer.add_edge ( 2 * n, T, k, 0 ) ; for ( int i = 1 ; i <= n ; ++ i ) { Lazer.add_edge ( l [i], r [i], 1, val [i] ) ; } for ( int i = 1 ; i < 2 * n ; ++ i ) { Lazer.add_edge ( i, i + 1, oo, 0 ) ; } printf ( "%d\n", Lazer.mcmf ( S, T ).second ) ; return 0 ; }
还有一种建图(边数复杂度是一样的):
# include <bits/stdc++.h> template < class T > inline bool chkmax ( T& d, const T& x ) { return d < x ? ( d = x ), 1 : 0 ; } template < class T > inline bool chkmin ( T& d, const T& x ) { return d > x ? ( d = x ), 1 : 0 ; } # define oo 0x3f3f3f3f # define N 1050 # define M 5050 class MaxCostMaxFlow { private : struct edge { int to, nxt, w, cost ; } g [M << 1] ; int S, T ; int head , dis , pre , ecnt ; inline bool spfa ( int S, int T ) { static std :: bitset < N > inq ; static std :: deque < int > Q ; inq.reset ( ) ; Q.clear ( ) ; memset ( pre, 0, sizeof ( int ) * ( T + 1 ) ) ; memset ( dis, -1, sizeof ( int ) * ( T + 1 ) ) ; Q.push_front ( S ) ; inq [S] = 1 ; dis [S] = 0x3f3f3f3f ; while ( ! Q.empty ( ) ) { int u = Q.front ( ) ; Q.pop_front ( ) ; inq [u] = 0 ; for ( int i = head [u] ; i ; i = g [i].nxt ) { int& v = g [i].to ; if ( g [i].w && chkmax ( dis [v], dis [u] + g [i].cost ) ) { pre [v] = i ; if ( ! inq [v] ) { ( Q.empty ( ) || dis [v] > dis [Q.front ( )] ) ? Q.push_front ( v ) : Q.push_back ( v ) ; inq [v] = 1 ; } } } } return ( bool ) pre [T] ; } public : MaxCostMaxFlow ( ) { ecnt = 1 ; memset ( head, 0, sizeof head ) ; } inline void clear ( ) { ecnt = 1 ; memset ( head, 0, sizeof head ) ; } inline void add_edge ( int u, int v, int w, int cost ) { g [++ ecnt] = ( edge ) { v, head [u], w, cost } ; head [u] = ecnt ; g [++ ecnt] = ( edge ) { u, head [v], 0, -cost } ; head [v] = ecnt ; } std :: pair < int, int > mcmf ( int S, int T ) { this -> S = S, this -> T = T ; int flow = 0, cost = 0, x ; while ( spfa ( S, T ) ) { x = oo ; for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) chkmin ( x, g [i].w ) ; for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) { g [i].w -= x, g [i ^ 1].w += x ; cost += x * g [i].cost ; } flow += x ; } return std :: make_pair ( flow, cost ) ; } } Lazer ; int dust ; int l , r , val ; # undef N # undef M int main ( ) { int n, k ; scanf ( "%d%d", & n, & k ) ; const int S = 2 * n + 5, T = 2 * n + 6 ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d%d", l + i, r + i ) ; if ( l [i] > r [i] ) std :: swap ( l [i], r [i] ) ; dust [( i << 1 ) - 1] = l [i], dust [i << 1] = r [i] ; val [i] = ( r [i] - l [i] ) ; } std :: sort ( dust + 1, dust + n + n + 1 ) ; for ( int i = 1 ; i <= n ; ++ i ) { l [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, l [i] ) - dust ; r [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, r [i] ) - dust ; } const int S1 = 2 * n + 1, T1 = 2 * n + 2 ; Lazer.add_edge ( S, S1, k, 0 ), Lazer.add_edge ( T1, T, k, 0 ) ; for ( int i = 1 ; i <= 2 * n ; ++ i ) { Lazer.add_edge ( S1, i, 1, 0 ), Lazer.add_edge ( i, T1, 1, 0 ) ; } for ( int i = 1 ; i <= n ; ++ i ) { Lazer.add_edge ( l [i], r [i], 1, val [i] ) ; } for ( int i = 1 ; i < 2 * n ; ++ i ) { Lazer.add_edge ( i, i + 1, oo, 0 ) ; } printf ( "%d\n", Lazer.mcmf ( S, T ).second ) ; return 0 ; }
相关文章推荐
- LOJ6122 「网络流 24 题 - 18」 航空路线问题 最长不相交路径 坠大费用坠大流
- 【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)
- LOJ6010 「网络流 24 题 - 11」数字梯形 坠大费用坠大流 坠大权不相交路径
- 线性规划与网络流24题之最长k可重区间集问题 最大权不相交路径(最大费用最大流)
- 【网络流24题】No.11(航空路线问题 最长不相交路径 最大费用流)
- 【网络流24题】 No.6 最长不减子序列问题 (最大流)[模型:最多不相交路径]
- loj6227「网络流 24 题」最长k可重线段集问题(类似loj6014 费用流)
- [网络流24题] 最长递增子序列 (最多不相交路径---网络最大流)
- nefu495最长k可重区间集问题【最大权不相交路径】网络流24题
- 【网络流24题】No.16 数字梯形问题 (不相交路径 最大费用流)
- loj6122「网络流 24 题」航空路线问题(最长不相交路径)
- [网络流24题] 06 最长递增子序列(最多不相交路径,最大流)
- LOJ6011「网络流 24 题 - 12」运输问题 坠小费用坠大流 坠大费用坠大流
- LOJ6012「网络流 24 题 - 13」分配问题 坠小费用坠大流 坠大费用坠大流
- 线性规划与网络流24——最长k可重区间集问题
- loj 6014「网络流 24 题」最长 k 可重区间集
- ★ 最长递增子序列问题 (最多不相交路径)(分层思想) 网络流最大流
- [网络流24题] 21 最长k可重区间集(最大权不相交路径 ,最小费用最大流)
- 「网络流 24 题」最长 k 可重区间集
- LOJ6005 「网络流 24 题 - 6」 最长递增子序列 坠大流