動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b, b吃c,c吃a。
現有n個動物,以1-n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。
有人用兩種說法對這n個動物所構成的食物鏈關係進行描述:
第一種說法是"1 x y",表示x和y是同類。
第二種說法是"2 x y",表示x吃y。
此人對n個動物,用上述兩種說法,一句接一句地說出k句話,這k句話有的是真的,有的是假的。當一句話滿足下列三條之一時,這句話就是假話,否則就是真話。
1) 當前的話與前面的某些真的話衝突,就是假話;
2) 當前的話中x或y比n大,就是假話;
3) 當前的話表示x吃x,就是假話。
你的任務是根據給定的n(1 <= n <= 50,000)和k句話(0 <= k <= 100,000),輸出假話的總數。
input
第一行是兩個整數n和k,以乙個空格分隔。
以下k行每行是三個正整數 d,x,y,兩數之間用乙個空格隔開,其中d表示說法的種類。
若d=1,則表示x和y是同類。
若d=2,則表示x吃y。
output
只有乙個整數,表示假話的數目。
sample input
100 7sample output1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
3我們先回顧一下並查集的基本操作
for(int i=1;i<=n;i++) father[i]=i;//令結點等於i,father[i]也可以等於-1
遞推**
int findfa(int x)
}
遞迴**
int findfa(int x)
void union(int a,int b)
遞推的壓縮
int findfa(int x)
while(a!=father[a])
return x;
}
遞迴的壓縮
int findfa(int v)
}
以上是最基本的並查集操作,那我們再來分析一下這道題。
我們首先要知道,題目是讓我們求關係是否正確,而不是求兩兩之間的關係,我們就可以根據有無關係來進行分類。有關係的就放到乙個並查集中去,沒有的就不用管,再在這個並查集中去驗證關係是否正確。
為了關係的簡化,我們將並查集中的所有關係進行路徑壓縮,每個點只與根節點判斷關係,這樣操作是最省時間的。
為了表達關係,我們開乙個r【】陣列,用來存p[x]->x的關係,
我們設 r[x]=0, 就是只p[x]與x同類
r[x]=1, p[x]吃掉x
r[x]=2, x吃掉p[x]
現在最難的就是關係的更新
我們假設 p[x]吃x x吃y 那麼y和p[x]的關係是什麼呢? 很顯然,y吃p[x], 食物鏈的關係 p[x]->x->y->p[x]。
我們現在分開寫 p[x]->y=p[x]->x+x->y; 是不是像向量形式(其實我是看的大佬的博文)我們繼續驗證 r[y]=r[x]+1=2 確實是y吃p[x]
(因為此時x與y的關係已知,y的父節點就是x的父節點p[x]),知道這個後,我們就可進行實現了。
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ll long long
#define ull unsigned long long
#define mod 1000000007
#define inf 0x7ffffff
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int n=50005;
int p[n],r[n];
int findfa(int x)
return p[x];
}int union(int d,int x,int y)
p[fay]=fax;
r[fay]=(r[x]+d-1+3-r[y])%3;//這裡找rootx->rooy=rootx->x+x->y+y->rooty 注意符號
return 0;
}int main()
if(union(d,x,y)) cot++;
}printf("%d\n",cot);
return 0;
}
並查集複習
定義陣列 fa x 表示 x 的父親 操作之前先要初始化每乙個節點的父親為自己 for int i 1 i n i fa i i 並查集基本操作 查詢,合併 查詢 查詢元素所在集合 int query int x 路徑壓縮 int query int x 遞迴版 int query int x 合併...
並查集 並查集
本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...
並查集入門(普通並查集 帶刪除並查集 關係並查集)
什麼是並查集?通俗易懂的並查集詳解 普通並查集 基礎並查集 例題 題解 how many tables problem description lh boy無聊的時候很喜歡數螞蟻,而且,還給每乙隻小螞蟻編號,通過他長期的觀察和記錄,發現編號為i的螞蟻會和編號為j的螞蟻在一起。現在問題來了,他現在只有...