POJ 1182 食物鏈(帶權並查集)

2021-07-04 15:55:35 字數 3369 閱讀 9533

a,b,c三種動物,a吃b, b吃c,c吃a。有n個動物,他們編號為1~n。

輸入:第一行n,k,分別表示動物個數,給出k句話(有真有假)。接下來n行每行一句話,每句的格式為三個整數:d,x,y。x,y為動物編號,d為1時表示x,y是同類,d為2時表示x吃y。

說明:假話有三種: 1) 當前的話與前面的某些真的話衝突,就是假話; 2) 當前的話中x或y比n大,就是假話; 3) 當前的話表示x吃x,就是假話。

輸出:假話的個數。一、r

elat

ion 的確定

對每乙個元素,把它對父節點的關係用陣列r[i]表示,即relation,作為權值。

由於數字d指定了後面給出的兩個動物的關係:

1)d=

1 時,d−

1=0 ,x,y是同類;

2)d=

2 時,d−

1=1 ,x吃y

這個權值不是隨便定的噢,且看下面推導~!

因此我們設r[i]包含這三種值,表示動物之間的三種關係:

1)r[

i]=0

時,i 與p[

i]是同類;

2)r[

i]=1

時,i 被p[

i]吃;3)r[

i]=2

時,i 吃p[

i];注:p[i]為i的父節點。

二、路徑壓縮 fi

nd_s

et(x

) 的節點演算法

我們知道,並查集的集合代表元是乙個元素,這裡規定集合出現的第乙個元素是代表元。

為了使查詢效率提高,我們需要使樹盡可能低,並查集的路徑壓縮讓它只有一層。

那麼怎麼把將不是直接聯絡的兩個節點成為父子關係?怎樣表明他們之間的關係呢?

這是我們接下來要推導的東西

根據兒子對父親的關係

r ,和父親對爺爺的關係

r推出兒子對爺爺的關係

r :

i

j k

爺爺 父親 兒子 兒子與爺爺

000=(i + j)%3 01

1=(i + j)%3 02

2=(i + j)%310

1=(i + j)%3 11

2=(i + j)%3 12

0=(i + j)%3 20

2=(i + j)%3 21

0=(i + j)%3 22

1=(i + j)%3

觀察即可知道,兒子對爺爺的關係是k=(i+j)%3。

為啥要這樣做?

可以畫個圖理解下。如:x->y,y->z,要把x的父節點設為z就需要上述步驟。

需要注意的是,每次更新節點的r[

i]時應該先找到父親節點再更新,否則會因為給出的話是假話而發生錯誤。

三、集合間關係的確定

初始時候每個元素都是自洽的,那麼有幾個集合的時候,怎麼確定集合(代表節點)之間的關係?

因為只有確定兩個集合(的代表節點)之間的關係才能把兩個集合合併最後得到乙個並查集。

先給出公式:r[

ry]=

(3−r

[y]+

(d−1

)+r[

x])

我們分3個小部分來推導:

(例如,由y−

>x−

>p,

y−>

q ,得到q−

>

p 。我們需要先得到q−

>

x ,再得到q−

>

p )畫圖更易理解。

(1)由子對父的關係得到父對子的關係

子對父

0(父子同類) (3

−0)%

3=0

1(父吃子) (3

−1)%

3=2 //父吃子

2(子吃父) (3

−2)%

3=1 //子吃父,一樣的哦親 即 r

[爺爺]

=(r[

子]+r

[父])

(2)q−

>

x ,把y接到x上,使q成為y的兒子,進而得到q對x的re

lati

on權值: r[

q對x]

=(r[

y對x]

+r[q

對y])

%3 r

[y對x

]=d−

1 r[

q對y]

=3−r

[y]

故r[q

對x]=

((d−

1)+(

3−r[

y]))

%3

(3)q−

>

p ,最後由q−

>x−

>

p 得到q−

>

p (得到q對p的 re

lati

on權值: r[

q對x]

=(r[

y對x]

+r[q

對y])

r[q對p]=

(r[y

對x]+

r[q對

y]+r

[x對p

]) 故

r[q對

p]=(

(d−1

)+(3

−r[y

])+r

[x])

題目只有一組樣例,如果按照多組來輸入會wa。

my

code

#include 

#include

using

namespace

std;

const

int n = (int)5e4 + 10;

int pa[n], r[n];

int ans;

int n, k;

void init()

}int find(int u)

void union(int x, int y, int d) else

}int main() else

if(d == 2 && x == y) else

}printf("%d\n", ans);

return

0;}

poj 1182 食物鏈 帶權並查集

這個題需要將動物分成3種,每次以y 0為物件,吃他的x為1,需要注意的是下一次碰到x cha函式遞迴更新與x有關的物件 include include include includeusing namespace std define n 50005 int father n num n int c...

poj1182食物鏈 帶權並查集

基本思路 帶權並查集 簡單的理解就是將有關係的點合併到乙個集合,記錄每個點到集合根節點的權重 include include include define max 50010 using namespace std int par max 記錄集合根節點 int offset max 記錄每個節點到...

poj 1182 食物鏈 帶權並查集

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