對於給定的開區間集合 i 和正整數 k,計算開區間集合 i 的最長 k可重區間集的長度。
輸入格式:
的第 1 行有 2 個正整數 n和 k,分別表示開區間的個數和開區間的可重迭數。接下來的 n行,每行有 2 個整數,表示開區間的左右端點座標。
輸出格式:
將計算出的最長 k可重區間集的長度輸出
輸入樣例#1: 複製
4 2輸出樣例#1: 複製1 76 8
7 10
9 13
15對於100%的資料,1\le n\le 5001≤n≤500 ,1\le k\le 31≤k≤3
確實比較難想
正解有兩種
借鑑一下學長的圖
首先離散化
第一種
這樣首先保證每個點都不會覆蓋超過$k$次
那麼對於乙個區間後面的區間,它對這個區間內的點是沒有影響的,故建一條如圖所示的邊
第二種
當選擇了乙個區間$(l,r)$後,相當於$(l,r)$這個區間內的點少了一次可以被選擇的機會
所以從$l$向$r$連邊
**為第2種
#include#include#include
#include
#include
#define addedge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0)
using
namespace
std;
const
int maxn=1e5+10
;const
int inf=1e6+10
;inline
intread()
while(c>='
0'&&c<='9')
return x*f;
}int
n,k,s,t;
int anscost=0
;struct
node
edge[maxn];
int head[maxn],num=2
;inline
void add_edge(int x,int y,int z,int
f)int
pre[maxn],vis[maxn],dis[maxn];
bool
spfa()}}
return dis[t]<=inf;
}void
f()void
mcmf()
int l[maxn],r[maxn],date[maxn],tot=0
;int
main()
sort(date+1,date+n*2+1
);
int num=unique(date+1,date+2*n+1)-date-1
;
for(int i=1;i<=n;i++)
l[i]=lower_bound(date+1,date+num-1,l[i])-date,
r[i]=lower_bound(date+1,date+num+1,r[i])-date;
for(int i=1;i<=num-1;i++)
addedge(i,i+1,0
,inf);
for(int i=1;i<=n;i++)
addedge(l[i],r[i],-(date[r[i]]-date[l[i]]),1
); addedge(s,
1,0,k);
addedge(num,t,
0,inf);
mcmf();
return0;
}
P3358 最長k可重區間集問題
題目鏈結 輸入最多500個點對,即離散化後最多有1000個座標。對離散化後的座標建圖。方法一 將座標從小到大連邊,乙個點與它後面相鄰的點建一條邊 流量為inf,花費為0 點對的左端點與右端點建一條邊 流量為1,花費為 區間長度 s與第乙個點建一條邊 流量為k,花費為0 最後乙個點與t建一條邊 流量為...
網路流 P3358 最長k可重區間集問題
對於給定的開區間集合 i 和正整數 k,計算開區間集合 i 的最長 k可重區間集的長度。輸入格式 的第 1 行有 2 個正整數 n和 k,分別表示開區間的個數和開區間的可重迭數。接下來的 n行,每行有 2 個整數,表示開區間的左右端點座標。輸出格式 將計算出的最長 k可重區間集的長度輸出 輸入樣例 ...
洛谷3358 最長k可重區間集問題(費用流)
點此看題面 說實話,這種題型是我長久以來一直很想知道怎麼做的,果然網路流二十四題真的是經典好題。我們可以把原題面改成選擇 k 次,每次可以選擇任意個不相交的區間。為了實現選 k 次,我們需要從超級源向第乙個點連一條容量為 k 價值為 0 的邊。然後,我們從座標軸上每個點向相鄰的下乙個點 最後乙個點向...