區間選點 II 差分約束

2021-10-23 05:12:22 字數 1908 閱讀 1096

題意

給定乙個數軸上的 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

53 7 3

8 10 3

6 8 1

1 3 1

10 11 1

sample output

6

題目大意還是給定若干個區間,並給出每個區間內至少要選取的點數,問最終最少選多少個點滿足每個區間上的條件。

另外這裡還附上學長推薦的差分約束問題相關部落格:spfa解差分約束問題

相比於貪心求解的方法,本題確實不容易想到可以用差分約束的方法。差分約束的關鍵就是要找到形如 xi - xj ≤ w 的約束條件,從而構造一條由 xi 指向 xj 的權值為 w 的邊,由此用最短路演算法得到的 dis[i] 就是差分約束問題的一組解。在差分約束問題中一定要注意最短路演算法起點的選取,要根據題目理解問題,畢竟最終的 dis[i] 是需要的結果。

本題也可以轉化為差分約束問題解決。我們可以看到對於區間 [i,j] ,j 之前區域包含的點的總數與 i 之前的區域包含的點的總數只差至少為 該段區間的 w 。這樣便可以轉換為差分約束問題,同時求解十分簡便,即 sum[j] - sum[i-1] ≥ w 。之後符號取反就是典型的差分約束問題了。另外還需要特別注意題目隱含著 0 ≤ sum[i] - sum[i-1] ≤ 1 這個條件,所以在構造邊的時候一定要加上。構造完成後用spfa演算法跑一遍最短路,得到最右端點的 dis 值就是答案。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define maxn 50005

#define inf 1e9

using

namespace std;

int tot,head[

4*maxn]

,vis[

3*maxn]

,dis[

3*maxn]

;struct edgeedge[

4*maxn]

;void

add(

int u,

int v,

int w)

void

spfa

(int s,

int e)

queue<

int> q;

q.push

(s);

vis[s]=1

; dis[s]=0

;while

(!q.

empty()

)}}}

}int

main()

for(

int i = s+

1; i <= e+

1; i++

)spfa

(s,e)

; cout <<

-dis[e]

<< endl;

return0;

}

差分約束 區間選點

給定乙個數軸上的 n 個區間,要求在數軸上選取最少的點使得第 i 個區間 ai,bi 裡至少有 ci 個點 輸入第一行乙個整數 n 表示區間的個數,接下來的 n 行,每一行兩個用空格隔開的整數 a,b 表示區間的左右端點。1 n 50000,0 ai bi 50000 並且 1 ci bi ai 1...

week8 A 區間選點 II(差分約束)

一 題目描述 給定乙個數軸上的 n 個區間,要求在數軸上選取最少的點使得第 i 個區間 ai,bi 裡至少有 ci 個點 使用差分約束系統的解法解決這道題 input 輸入第一行乙個整數 n 表示區間的個數,接下來的 n 行,每一行兩個用空格隔開的整數 a,b 表示區間的左右端點。1 n 50000...

差分約束 區間選點。c

區間選點 給定乙個數軸上的 n 個區間,要求在數軸上選取最少的點使得第 i 個區間 ai,bi 裡至少有 ci 個點,要求使用差分約束 輸入第一行乙個整數 n 表示區間的個數,接下來的 n 行,每一行兩個用空格隔開的整數 a,b 表示區間的左右端點。1 n 50000,0 ai bi 50000 並...