https://ac.nowcoder.com/acm/contest/22904/1024
參考
https://www.luogu.com.cn/problem/solution/P2024
這是一個典型的並查集問題,可以透過“帶有偏移的並查集”來解決。由於題目涉及食物鏈的關係,可以將“同類”與“吃”的關係進行合併操作和衝突檢測。
這裡我們使用一種特殊的並查集,即帶有偏移的並查集來處理這個問題,將每個動物的狀態分為3類狀態。
以下是解題思路和程式碼示例:
思路
定義並查集:每個動物有3種狀態(自己、吃它的和被它吃的),將每個動物的3種狀態分別表示為 i、i+N、i+2N。
i 表示第 i 個動物的 "A 類"
i+N 表示第 i 個動物的 "B 類"
i+2N 表示第 i 個動物的 "C 類"
合併關係:
如果兩個動物是同類(D=1),那麼它們的三種狀態需要分別相等。
如果 X 吃 Y(D=2),則 X 的狀態應該在 Y 的前一個狀態上。
判斷假話:
如果 X 或 Y 超出 N,或者 X 吃 X,則必定是假話。
如果當前的話與之前建立的關係產生衝突,則是假話。
// 並查集模板省略
int main() {
int N, K;
cin >> N >> K;
UnionFind uf(3 * N + 1);
int falseCount = 0;
while (K--) {
int D, X, Y;
cin >> D >> X >> Y;
if (X > N || Y > N || (D == 2 && X == Y)) {
falseCount++;
continue;
}
if (D == 1) {
if (uf.isConnected(X, Y + N) || uf.isConnected(X, Y + 2 * N)) {
falseCount++;
} else {
uf.unite(X, Y);
uf.unite(X + N, Y + N);
uf.unite(X + 2 * N, Y + 2 * N);
}
} else if (D == 2) {
if (uf.isConnected(X, Y) || uf.isConnected(X, Y + 2 * N)) {
falseCount++;
} else {
uf.unite(X, Y + N);
uf.unite(X + N, Y + 2 * N);
uf.unite(X + 2 * N, Y);
}
}
}
cout << falseCount << endl;
return 0;
}