種樹(一道簡單的差分約束系統)

2021-08-02 16:24:24 字數 2243 閱讀 4448

為了綠化鄉村,h村積極響應號召,開始種樹了。

h村里有n幢房屋,這些屋子的排列順序很有特點,在一條直線上。於是方便起見,我們給它們標上1~n。樹就種在房子前面的空地上。

同時,村民們向村長提出了m個意見,每個意見都是按如下格式:希望第li個房子到第ri個房子的房前至少有ci棵樹。

因為每個房屋前的空地面積有限,所以每個房屋前最多只能種ki棵樹。

村長希望在滿足村民全部要求的同時,種最少的樹以節約資金。請你幫助村長。

輸入檔名為tree.in

輸入第1行,包含兩個整數n,m。

第2行,有n個整數ki。

第2~m+1行,每行三個整數li,ri,ci。

輸出檔名為tree.out

輸出1個整數表示在滿足村民全部要求的情況下最少要種的樹。村民提的要求是可以全部滿足的。

tree.in
5 3
1 1 1 1 1
1 3 

2

4 2 

4 5 1
tree.out
3
tree.in
4 3
3 2 4 1
1 2 4
2 3 5
2 4 6
tree.out
8

【輸入輸出樣例解釋1】 如圖是滿足樣例的其中一種方案,最少要種3棵樹。
【輸入輸出樣例解釋2】如圖是滿足樣例的其中兩種方案,左圖的方案需要種9棵樹,右圖的方案需要種8棵樹。可以驗證,最少需要種8棵樹。
【資料範圍】

對於30%的資料,0

對於50%的資料,0

對於70%的資料,0

對於100%的資料,0

用s陣列表示字首和,很容易列出不等式s[r[i]]-s[l[i]-1]>=c[i],和s[i]-s[i-1]<=k[i],還有乙個比較容易忘記(我就忘了,然後炸飛)s[i]-s[i-1]>=0

看到這一串不等式,差分約束系統就很明顯了。移項,得到s[r[i]]>=s[l[i]-1]+c[i],s[i]>=s[i-1]+0,s[i-1]>=s[i]+(-k[i]),根據三角形不等式連變,l[i]-1到r[i]連一條權值為c[i]的邊(1<=i<=m),i-1到i連一條權值為0的邊(1<=i<=n),i到i-1連一條權值為-k[i]的邊(1<=i<=n)。

然後跑最長路spfa。

附上**

#include#include#include#include#include#include#includeusing namespace std;
int n,m,vet[3000000],next[3000000],head[1000000],en,b[1000000],s,t;

bool vis[1000000];

long long w[3000000],dis[1000000];

queueq;

void addedge(int u,int v,long long val)

int main()

for(int i=1;i<=m;i++)

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

addedge(n+1,i,0);

for(int i=1;i<=n;i++)

addedge(i-1,i,0);//不要忘記

s=n+1;

t=n;

vis[s]=true;

b[s]=1;

q.push(s);

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

dis[i]=-1000000000;

while(!q.empty())

} }

} printf("%lld\n",dis[t]);

return 0;

}

差分約束系統專題 對差分約束系統的理解

具體能解決的問題 求最長路,最短路,或者判斷解是否存在。在建邊的時候 一般是給你區間減法的關係,或者是這個點到另乙個點的關係。如果給你的關係是除法的話,我們可以通過使用兩邊同時取log的方式,將除法變成兩個式子的減法,這樣就轉換成了減法的建邊。判斷最優解的時候 一般是判斷是否有負環或者正環,但是乙個...

樹鏈差分的一道題

description 給出一棵有向樹,有點權和邊權,定義乙個節點i的答案為以i為根的子樹中有多少j的點權不小於j i的簡單路徑上邊權和,求所有點的答案 input 第一行一整數t表示用例組數,每組用例首先輸入樹上點數n,之後n個整數x i 表示第i個點的點權,最後n 1行每行三個整數u,v,w表示...

差分約束系統的簡介

一直不知道差分約束是什麼型別題目,最近在寫最短路問題就順帶看了下,原來就是給出一些形如x y b不等式的約束,問你是否滿足有解的問題 好神奇的是這類問題竟然可以轉換成圖論裡的最短路徑問題,下面開始詳細介紹下 比如給出三個不等式,b a k1,c b k2,c a k3,求出c a的最大值,我們可以把...