洛谷P3358 最長k可重區間集問題 費用流

2022-04-30 15:12:14 字數 2282 閱讀 3486

對於給定的開區間集合 i 和正整數 k,計算開區間集合 i 的最長 k可重區間集的長度。

輸入格式:

的第 1 行有 2 個正整數 n和 k,分別表示開區間的個數和開區間的可重迭數。接下來的 n行,每行有 2 個整數,表示開區間的左右端點座標。

輸出格式:

將計算出的最長 k可重區間集的長度輸出

輸入樣例#1: 複製

4 2

1 76 8

7 10

9 13

輸出樣例#1: 複製

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 的邊。然後,我們從座標軸上每個點向相鄰的下乙個點 最後乙個點向...