帶權並查集 then

2021-08-07 07:45:12 字數 2964 閱讀 2039

問題 b: 便

時間限制: 2 sec 記憶體限制: 512 mb

提交: 50 解決: 14

題目描述

給出乙個r*c的棋盤.共有r行c列,r*c個格仔.現要在每個格仔都填乙個非負整數.使得任意乙個2*2的正方形區域都滿足這樣的性質:左上角的數字+右下角的數字=左下角的數字+右上角的數字.有些格仔已經確定,你不能更改其中的數字.其他格仔的數字由你決定.

不難驗證每個2*2的區域都是符合要求的.

orbitingflea想要知道乙個可行的填充棋盤的方案.但是這個方案可能很大.所以你只需對給定的棋盤判定是否存在至少一種可行的填充棋盤的方案.

輸入 第一行輸入乙個t,表示資料組數。接下來t組資料。

每組資料的第1行2個整數r,c表示棋盤的大小.

第2行1個整數n表示已經被填好數字的格仔的數目.

接下來n行每行3個整數ri,ci,ai,表示第ri行ci列的格仔被填上了數字ai.

輸出 t行.第i行是第i組資料的答案.有合法方案時輸出一行yes,沒有時輸出一行no.

樣例輸入

6 2 2 3

1 1 0

1 2 10

2 1 20

2 3 5

1 1 0

1 2 10

1 3 20

2 1 30

2 3 40

2 2 3

1 1 20

1 2 10

2 1 0

3 3 4

1 1 0

1 3 10

3 1 10

3 3 20

2 2 4

1 1 0

1 2 10

2 1 30

2 2 20

1 1 1

1 1 -1

樣例輸出

yes

no no

yes

no no

提示 第1個測試點,r=1

第2,3個測試點,r*c<=12,如果有解,保證存在乙個解使得所有數字大小不超過2

第4,5個測試點,r=2

第6,7個測試點,r=3

第8個測試點,1<=r,c<=20

第9個測試點,1<=r,c<=100

對於全部測試點,1<=t<=6,1<=r,c,n<=100000,1<=ri<=r,1<=ci<=c,同乙個格仔不會多次被填上數字.ai是整數且絕對值不超過10^9.

這道題翻譯成中文竟然叫 便。。。。→_→

對於這個棋盤,要滿足l1+r2==l2+r1,換言之l1-l2==r1-r2.從左向右以此類推。

因此,對於某一行,它與另一行對應列的差值相等。那麼,這就和並查集很像了。可以通過已確定的點,實現行列間的的比較。而且差具有傳遞性,所以完全可以用帶權並查集。

那麼舉個例子,行1和行2確定了差值,行2和行3確定了,就可以間接確定行1和行3的差,就把行3連成行1的兒子。

如果有合併,此處考慮兩個問題。

1,如果當前兩行已經有同乙個父親,那麼如果他們的當前差不等於他們與父親確定的差值的差,那麼就可以返回無解了。

2,對於父親的合併cha[fx]=cha[x,y]+cha[y]-cha[x];其實也挺好理解的。。

這個處理完後,那麼就不會再存在互相矛盾的情況了,但還有一種情況,就是出現值小於零。那麼如何判斷呢?

對於所有確定值的點,那麼它可以給父親行提供乙個值,(因為行與行之間的差確定了,那麼確定的點值就可以給父親行對應列乙個確定的值),那麼求出這個最小值。然後找出父親與兒子最大的那個差。這樣就找到了此聯通塊中的最小值了。判斷是否小於零即可。

#include

#include

#include

#include

#include

#define n 100000

#define ll long long

using

namespace

std;

int read()

while(x>='0'&&x<='9')sum=sum*10+x-'0',x=getchar();

return sum*f;

}int r,c,n,p=1,t;

int fx[n+5],fy[n+5];

ll wx[n+5],wy[n+5],hh1[n+5],hh2[n+5];

struct node

inline node(int x_,int y_,ll h_)

}a[n+5];

inline

bool cmp1(node a,node b)

inline

int find_y(int x)

inline

int hb_x(int x,int y,ll l)

inline

int hb_y(int x,int y,ll l)

inline

int work()

if(p==0)return

0; sort(a+1,a+n+1,cmp1);

for(int i=1;iif(a[i].x==a[i+1].x&&!hb_y(a[i].y,a[i+1].y,a[i+1].h-a[i].h))

return

0; sort(a+1,a+n+1,cmp2);

for(int i=1;iif(a[i].y==a[i+1].y&&!hb_x(a[i].x,a[i+1].x,a[i+1].h-a[i].h))

return

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

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

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

if(fx[i]==i&&hh1[i]+hh2[i]<0)

return

0; return1;}

int main()

}

並查集,帶權並查集

題意 ignatius過生日,客人來到,他想知道他需要準備多少張桌子。然而一張桌子上面只能坐上相互熟悉的人,其中熟悉可定義成為a與b認識,b與c認識,我們就說a,b,c相互熟悉 例如a與b熟悉and b與c熟悉,d與e熟悉,此時至少需要兩張桌子。輸入 t表示樣例個數,n表示朋友個數,朋友從1到n編號...

帶權並查集

食物鏈 time limit 1000ms memory limit 10000k total submissions 71395 accepted 21146 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...

帶權並查集

這幾天遇到了兩次帶權並查集,帶權並查集其實就是並查集加入了權值的屬性。帶權並查集和普通並查集的區別主要體現在合併和查詢上,普通並查集的查詢 int findset int x 我們以食物鏈的帶權並查集為例 int findset int x 帶權並查集的查詢操作裡只加入了一行ranks的操作,而且r...