HNOI2005 狡猾的商人 一題兩解

2021-09-26 16:09:28 字數 2713 閱讀 3304

題目鏈結

題目大意:

一段區間,給定m個資訊,每個資訊表示一段子區間中的區間和,問你這個區間是否合法(也就是說是否存在這種區間)

第一種解法:差分約束:

由於是一段區間和,那我們不妨把它看成是字首和形式的兩個相減。然後將它用差分約束的方式轉換成一張圖,那麼這個區間是否合法就變成了這張圖上是否有最短路,就變成了用spfa判負環的問題。

1.建圖:

對於一條資訊:at−

as==

x(

t>=s

)a_t-a_s==x(t>=s)

at​−as

​==x

(t>=s

)那麼就可以變為從s-1到t有一條長度為x的邊,然後這條邊必須在s-1到t的最短路徑中。

那麼如何判斷是否合法呢?這裡有乙個技巧就是將邊反向,邊權變為原來的相反數然後判負環。

證明:如果這條邊p不在從s-1到t的最短路中,那麼一定有一條路徑k(注意,這是路徑,有可能是由多條邊合在一起組成)從s-1到t並且其長度enp

len_p

lenp

​。那麼將邊權變為負數之後就是len

k>le

np

len_k>len_p

lenk

​>le

np​,這個時候我們再跑spfa的時候我們在s-1這個點去t的時候會走p,從t會選擇k的反向路徑回到s-1,由於len

p

nk

len_ple

np​nk

​所以會有len

p+(−

lenk

)<

0len_p+(-len_k)<0

lenp​+

(−le

nk​)

<

0,這時候就構成了乙個負環。

如何用spfa判負環?

我們用cnt

[i

]cnt[i]

cnt[i]

表示在搜最短路的時候i這個點入佇列(也就是訪問)多少次。

如果i

>=n

i>=n

i>=n

那我們就找到了乙個負環。具體關於差分約束與spfa演算法請自行學習。

下附ac**:

#include

#include

#include

#include

using

namespace std;

intread()

while

(s>=

'0'&&s<=

'9')

return x*f;

}int w;

int n,m;

struct edgee[

2020];

int eid=

0,head[

1010];

void

insert

(int u,

int v,

int l)

bool vis[

110]

;int cnt[

110]

;int dist[

110]

;bool

spfa()

if(cnt[x]

>=n)

return

false;}

}}return

true;}

intmain()

if(spfa()

)else

printf

("false\n");

}}

第二種解法:帶權並查集

好處:上面的差分約束我們每一條資訊轉化為一條邊然後跑最短路,但是帶權並查集可以一邊讀入資訊一邊處理判斷,這樣的話省去最短路的時間後,時間會變得更快。

85ms / 784.00kb / 748b c++ 帶權並查集

265ms / 820.00kb / 1.37kb c++ 差分約束

下面我們開始介紹這種解法。

1.帶權並查集:

與並查集類似,只不過我們在合併過程中帶乙個權值

sum[x]表示的是中x到其祖先這段區間的和

注意:我們合併的時候是永遠用輸入資訊中的兩個點靠後的去合併到靠前的,而不是祖先節點。所以雖然說我們是相對靠後的合併到相對靠前的,但是並不代表乙個點的祖先節點一定比這個點靠後。

下附ac**:

#include

#include

using

namespace std;

int w;

int n,m;

int f[

110]

;int sum[

110]

;int flag=1;

intget

(int x)

void

merge

(int a,

int b,

int c)

else

return;}

intmain()

memset

(sum,0,

sizeof

(sum));

flag=1;

for(

int i=

1;i<=m;i++)if

(flag)cout<<

"true"

"false"

<}}

HNOI2005 狡猾的商人

刁奼接到乙個任務,為稅務部門調查一位商人的賬本,看看賬本是不是偽造的。賬本上記錄了n個月以來的收入情況,其中第i 個月的收入額為ai i 1,2,3 n 1,n 當 ai大於0時表示這個月盈利ai 元,當 ai小於0時表示這個月虧損ai 元。所謂一段時間內的總收入,就是這段時間內每個月的收入額的總和...

HNOI2005狡猾的商人

傳送門 題目意思很簡單,意思是說給你一些區間和,要你判斷這些區間和是否合法。開始只想到了差分約束的方法,就是搞成字首和的形式 su m r sum l 1 w 且 su m r sum l 1 w 這樣利用spfa建圖,利用三角形不等式,即dis v dis x w i 每個條件建出sum r su...

HNOI2005 狡猾的商人

hnoi2005 狡猾的商人 time limit 10 sec memory limit 162 mb description 刁奼接到乙個任務,為稅務部門調查一位商人的賬本,看看賬本是不是偽造的。賬本上記錄了n個月以來的收入情況,其中第i 個月的收入額為ai i 1,2,3 n 1,n 當 ai...