「网络流 24 题」最长 k 可重区间集

给定区间集合$I$和正整数$k$, 计算$I$的最长$k$可重区间集的长度.

区间离散化到$[1,2n]$, $S$与$1$连边$(k,0)$, $i$与$i+1$连边$(k,0)$, $2n$与$T$连边$(k,0)$. 对于每个区间$(l,r)$, $l$与$r$连边$(1,l-r)$.

最小费用相反数就为最大长度

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#include <unordered_map>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, P2 = 998244353, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<‘0‘||p>‘9‘)p=getchar();while(p>=‘0‘&&p<=‘9‘)x=x*10+p-‘0‘,p=getchar();return x;}
//head

#ifdef ONLINE_JUDGE
const int N = 1e6+10;
#else
const int N = 999;
#endif

int n, m, k, S, T;
struct _ {int from,to,w,f;};
vector<_> E;
vector<int> g[N];
int a[N], pre[N], inq[N], d[N];
int mf,mc;
queue<int> q;
void add(int x, int y, int c, int w) {
    g[x].pb(E.size());
    E.pb({x,y,c,w});
    g[y].pb(E.size());
    E.pb({y,x,0,-w});
}
void mfmc() {
	mf=mc=0;
    while (1) {
        REP(i,1,T) a[i]=d[i]=INF,inq[i]=0;
        q.push(S),d[S]=0;
        while (!q.empty()) {
            int x=q.front(); q.pop();
            inq[x] = 0;
            for (auto t:g[x]) {
                auto e=E[t];
                if (e.w>0&&d[e.to]>d[x]+e.f) {
                    d[e.to]=d[x]+e.f;
                    pre[e.to]=t;
                    a[e.to]=min(a[x],e.w);
                    if (!inq[e.to]) {
                        inq[e.to]=1;
                        q.push(e.to);
                    }
                }
            }
        }
        if (a[T]==INF) break;
        for (int u=T;u!=S;u=E[pre[u]].from) {
            E[pre[u]].w-=a[T];
            E[pre[u]^1].w+=a[T];
        }
        mf+=a[T],mc+=a[T]*d[T];
    }
}

int b[N], l[N], r[N];
int main() {
	scanf("%d%d", &n, &k);
	REP(i,1,n) {
		scanf("%d%d",l+i,r+i);
		b[++*b]=l[i],b[++*b]=r[i];
	}
	sort(b+1,b+1+*b),*b=unique(b+1,b+1+*b)-b-1;
	REP(i,1,n) {
		l[i]=lower_bound(b+1,b+1+*b,l[i])-b;
		r[i]=lower_bound(b+1,b+1+*b,r[i])-b;
	}
	S = *b+1, T = S+1;
	add(S,1,k,0),add(*b,T,k,0);
	REP(i,2,*b) add(i-1,i,k,0);
	REP(i,1,n) add(l[i],r[i],1,-b[r[i]]+b[l[i]]);
	mfmc();
	printf("%d\n", -mc);
}

原文地址:https://www.cnblogs.com/uid001/p/10990261.html

时间: 2024-10-09 15:12:58

「网络流 24 题」最长 k 可重区间集的相关文章

*LOJ#6227. 「网络流 24 题」最长k可重线段集问题

$n \leq 500$条平面上的线段,问一种挑选方法,使得不存在直线$x=p$与挑选的直线有超过$k$个交点,且选得的直线总长度最长. 横坐标每个点开一个点,一条线段就把对应横坐标连一条容量一费用(-长度)的边:点$x$向点$x+1$连一条容量$k$费用0的边.这里的$k$边限制的是直线上其他不经过这里的地方. 这里有个trick就是有与$x$轴垂直的线段.直接判掉会wa.为此把坐标扩大两倍,如果$l=r$那么$r++$否则$l++$,相当于把一个点拆成两个. 原文地址:https://www

网络流24题之最长k可重线段集问题

对于每个线段拆成两个点,如同之前一样建图,由于可能出现垂直于x轴的 所以建图由i指向i~ 继续最小费用最大流 By:大奕哥 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=10000005,inf=1e9; 4 int head[N],d[N],f[N],l1[N],r1[N],l2[N],r2[N],a[N],s=1e9,t,n,k,cnt=-1; 5 long long cost; 6 bool v[N]; 7

「网络流24题」「LuoguP3358」 最长k可重区间集问题

题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数.接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标. 输出格式: 将计算出的最长 k可重区间集的长度输出 输入输出样例 输入样例#1: 复制 4 2 1 7 6 8 7 10 9 13 输出样例#1: 复制 15 说明 对于100%的数据,1<=n<=500,1<=k<

「网络流24题」最长不下降子序列问题

传送门:>Here< 题意: 给定正整数序列$x_1,...,x_n$ (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用$x_1$和$x_n$,则从给定序列中最多可取出多少个长度为$s$的不下降子序列. 思路分析 题意首先就很坑:注意第二问中的取出二字,意味着一个数字最多只能存在于一个LIS中.所以才会有第三问的假设 第一问很简单,直接暴力$O(n^2)$就好了 后面的两问需要借助于网络流.很容易想到

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,?,Em} E = \{ E_1, E_2, \cdots, E_m \}E={E?1??,E?2??,?,E?m??},和进行这些实验

「网络流24题」2. 太空飞行计划问题

「网络流24题」2. 太空飞行计划问题 <题目链接> 最大权闭合子图. 源点与实验连边权为实验费用的有向边: 仪器与汇点连边权为仪器费用的有向边: 实验与仪器之间连边权为INF的有向边. 答案为所有与源点相连的边的边权和减去图的最小割. 证明见国集队员胡伯涛论文<最小割模型在信息学竞赛中的应用>. 输出路径时,最后一次层次图中: 与源点相连的点即选做的实验:与汇点相连的点即选用的仪器. 注意 ·读入数据时,读到空格继续,否则停止. ·仪器部分的点权+50,避免两部点权相同. #in

「网络流24题」 9. 方格取数问题

「网络流24题」 9. 方格取数问题 <题目链接> 二分图的最大点权独立集 建立二分图,使得每个点与其相邻的点在不同的部. 源向X部引有向边,Y部向汇引有向边,边权为点权. X部每个点到其相邻的点引有向边,边权INF,这个边的两个断电不能同时被选. 那么S-X-Y-T的任意一条增广路都表示选了两个相邻的点. 于是问题转化为求网络最小割. 最终的答案为所有点的点权和(先都选上)减去网络最小割(不能选的最小点权集). #include <algorithm> #include <

「网络流24题」 5. 圆桌问题

「网络流24题」 5. 圆桌问题 <题目链接> 二分图多重匹配. 多对多. 匈牙利似乎真的不太好办了. 所以乖乖最大流吧. 套路建模,S->每个单位(边权=单位代表数):每个餐桌->T(边权=餐桌容量):每个单位->每个餐桌(边权=1). 跑最大流. 最大流等于总代表数则有解,否则无解. 每个单位的出边中,每条满流边的终点便是这一单位每个代表的餐桌号. #include <algorithm> #include <climits> #include &