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