差分約束 解決區間選點問題

2021-10-04 23:49:43 字數 1886 閱讀 2636

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

輸入第一行乙個整數 n 表示區間的個數,接下來的 n 行,每一行兩個用空格隔開的整數 a,b 表示區間的左右端點。1 <= n <= 50000, 0 <= ai <= bi <= 50000 並且 1 <= ci <= bi - ai+1。

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

樣例資料:

input:

5

3 7 3

8 10 3

6 8 1

1 3 1

10 11 1

6
(小聲說,如果是自己寫題,肯定是無論如何也想不到這麼高階的差分約束的做法。)用差分約束,主要就是思考如何構建差分約束的條件,即如何構建差分約束的圖。將圖構建完成後,利用spfa來根據題意,是跑最常路還是最短路,修改條件即可。

構建圖:首先要構造不等式組。可以記sum[i](在此處用的dis),為數軸【0,i】之間需要選點的個數。

**對於第i個區間[ai,bi]之間需要滿足,sum[bi]-sum[ai-1]>=ci,其中ci即為這個區間需要選點的個數,另外為了保證sum有意義,需要保證 0<=sum[i]-sum[i-1]<=1。**根據上述的條件即可構建圖來。

如何構建圖:

在此附上學長給的鏈結,跟著說明來構建圖還是能理解的。

即按照上述來選擇起始點和終點以及邊權,構建好圖,在利用spfa即可得到所需要的解。注意跑最短路得到的是最大解,跑最長路得到的是最小的解。還要注意在這樣構建時,由於左區間,即起始點有a-1的限制,故原先的起點0會多出來乙個-1點,即增加乙個點即可(如果這個點沒有路,多出來的-1也並不影響,因為其到0的距離為0)。

#include 

#include

#include

#include

#include

#include

using namespace std;

int n;

int a, b,c;

int dis[50010]

; //記錄長度

int vis[50010]

; //是否在佇列中

int cnt[50010]

; //記錄到達該點所經歷的邊數

struct edgee[200050]

;int head[50010]

;int tot; //當前的邊數

queue q;

// 到哪點 去哪點 權值

void add_edge(int t, int f, int w)

queue q2;

bool vis2[205]

; void bfs(int x)

i = e[i].next;}}

}void spfa(

)else if(dis[t1]

!=-1 && vis[t1]

==0)

} i = e[i].next;}}

}int main()

for(int i=0; i<50001; i++)

for(int i=0; i

spfa();

cout<

<

}

差分約束 區間選點

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

區間選點 差分約束系統問題

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

差分約束 區間選點。c

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