A 區間選點

2021-10-05 03:30:28 字數 2282 閱讀 7635

給定乙個數軸上的 n 個區間,要求在數軸上選取最少的點使得第 i 個區間 [ai, bi] 裡至少有 ci 個點

使用差分約束系統的解法解決這道題

使用差分約束系統的解法解決這道題

使用差分約束系統的解法解決這道題

使用差分約束系統的解法解決這道題

使用差分約束系統的解法解決這道題

input

輸入第一行乙個整數 n 表示區間的個數,接下來的 n 行,

每一行兩個用空格隔開的整數 a,b 表示區間的左右端點。

1 <= n <= 50000, 0 <= ai <= bi <= 50000 並且 1 <= ci <= bi - ai+1。

output

輸出乙個整數表示最少選取的點的個數
sample input

5

3 7 3

8 10 3

6 8 1

1 3 1

10 11 1

sample output

6
本題核心內容為差分約束系統。

差分約束系統為一種特殊的n元不等式組,包含 n 個變數以及 m 個約束條件。

其中每個約束條件是由兩個其中的變數做差構成的,形如xi-xj≤ck(ck是常數)。

我們要解決的問題是:求一組解使得所有的約束條件得到滿足,否則判斷出無解。

那如何轉化呢?

通過移項,可以得到xi≤xj+ck。這個形式與dis[i]≤dis[j]+w非常相似,所以我們通過這個式子將兩者聯絡起來。

同時,因為求單源路徑都是最短路/最長路,只乙個最值,所以最終得到的答案都是等於號成立的情況。那麼,想要求最大值,跑最短路,求最小值,跑最長路。

其中,求單源最短/長路,我們選用spfa演算法,本題不存在負環等情況,所以沒有進行優化,若可能出現負環/無法到達等情況,可以利用優化的spfa/bellman演算法。

#include

#include

#include

#include

using

namespace std;

int t=

0,a=

0,b=

0,c=

0,q=

100000

,p=0

,tot=0;

int a[

50500]=

;int head[

50500

],inq[

50500

],dis[

50500];

queue<

int> q;

struct edgeedge[

160000];

void

init()

}void

spfa

(int s)

memset

(inq,0,

sizeof

(inq));

memset

(dis,-1

,sizeof

(dis));

dis[s]=0

; inq[s]=1

; q.

push

(s);

while

(!q.

empty()

)}}}

}int

main()

//記錄最大最小點

if(aedge[

++tot]

.to=b+1;

edge[tot]

.next=head[a]

; head[a]

=tot;

edge[tot]

.w=c;

}//新增邊

//繼續插邊使得相鄰sum之差總是大於等於0,小於等於1

for(

int i=q;i)spfa

(q);

printf

("%d\n"

,dis[p]);

}

最需要注意的一點是,為了控制0<=sum[i]-sum[i-1]<=1,需要在增加完所有輸入的邊之後,繼續向圖中加邊!

包含memset的標頭檔案為string.h!不要混淆,不是cstring也不是string。

可以把本題中重複出現的加邊操作寫為乙個函式,在主函式中重複呼叫它即可。

B 區間選點

數軸上有 n 個閉區間 a i,b i 取盡量少的點,使得每個區間內都至少有乙個點 不同區間內含的點可以是同乙個 第一行1個整數n n 100 第2 n 1行,每行兩個整數a,b a,b 100 乙個整數,代表選點的數目。input 21 5 4 6output 1input 31 3 2 54 6...

B 區間選點

數軸上有 n 個閉區間 a i,b i 取盡量少的點,使得每個區間內都至少有乙個點 不同區間內含的點可以是同乙個 input 第一行1個整數n n 100 第2 n 1行,每行兩個整數a,b a,b 100 output 乙個整數,代表選點的數目examples input 2 1 54 6outp...

區間選點 貪心

給定n個閉區間 ai,biai,bi 請你在數軸上選擇盡量少的點,使得每個區間內至少包含乙個選出的點。輸出選擇的點的最小數量。位於區間端點上的點也算作區間內。輸入格式 第一行包含整數n,表示區間數。接下來n行,每行包含兩個整數ai,biai,bi,表示乙個區間的兩個端點。輸出格式 輸出乙個整數,表示...