從0
∼50000
0\sim50000
0∼5000
0中選擇盡量少的數字使得n
nn組形如「x
xx到y
yy中選擇的數字不少於c
kc_k
ck個」的要求全部滿足。
設s
is_i
si表示從0∼i
0\sim i
0∼i中選擇的數字個數。那麼對於任意乙個要求x,y
,c
kx,y,c_k
x,y,ck
,都需要滿足sy+
1−sx
≥c
ks_-s_x\geq c_k
sy+1−
sx≥
ck,與差分約束十分相像。於是從y
yy連向x
xx一條長度為c
kc_k
ck的邊。
同時我們對於數字i
ii,肯定是要麼選擇,要麼不選。所以本題中還有兩個隱含條件sk−
sk−1
≥0
s_k-s_\geq 0
sk−sk
−1≥
0,sk−s
k−1≤
1s_k-s_\leq 1
sk−sk
−1≤
1。對於條件1,可以直接從k−1
k-1k−
1向kk
k連一條長度為0的邊,對於條件2,變形得sk−
sk−1
≥−
1s_k-s_k-1\geq -1
sk−sk
−1≥
−1,從k
kk向k−1
k-1k−
1連一條長度為-1的邊。
由於不等式符號全部是大於,所以需要跑最長路。很明顯圖中是不含正環的,所以可以不用判正環。以-1為源點跑spf
aspfa
spfa
即可。答案即為dis
[50000
]dis[50000]
dis[50
000]
。但是下標是不可以用負數的。所以可以把所有點的下標+1,變成「從1
∼50001
1\sim50001
1∼5000
1」中選擇,從0開始跑spf
aspfa
spfa
,答案就是dis
[50001
]dis[50001]
dis[50
001]
。
#include
#include
#include
using
namespace std;
const
int n=
50010
;int n,x,y,z,tot,head[n]
,dis[n]
;bool vis[n]
;struct edge
e[n*3]
;void
add(
int from,
int to,
int dis)
void
spfa()
}}}}
intmain()
for(
int i=
1;i<=
50001
;i++
)add
(i-1
,i,0),
add(i,i-1,
-1);
spfa()
;printf
("%d\n"
,dis[
50001])
;return0;
}
差分約束 poj 1201 Interval
差分約束 poj 1201 又是一道vector tle。確實很好的差分約束。很好的差分約束,注意隱含條件 0 d i 1 d i 1 題目保證了沒負圈。include include include using namespace std define n 50005 define inf 100...
POJ 1201 樹狀陣列
給你n個區間,每個區間為 a,b 每個區間取c個數構成乙個集合,求集合最小容量 把區間按b排序,從第乙個區間開始取,從後往前取,這樣盡可能和後面的區間重複 另外如果我們發現當前區間取得個數已經超過了c,那麼只需要讓之前區間換就行,而總數是不變的,所以不用更新答案 求當前區間已經取了多少個數用樹狀陣列...
poj 1201 差分約束
傳送門 題意 ai到bi間至少有ci個元素,問所有數中至少有多少元素。額。這樣好像說不清楚,我拿樣例說下吧。3到7之間至少有3個元素,8到10之間至少有3個元素,6到8之間至少有1個元素,1到3之間至少有1個元素,10到11之間至少有1個元素。最少情況如下 1 2 3 4 5 6 7 8 9 10 ...