poj 1182 食物链
这道题其实还不是太明白
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
class UnionFind {
int[] parent;
int[] size;
int count;
public UnionFind(int n) {
count = n;
parent = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
size[i] = 1;
}
}
public int find(int p) {
while (p != parent[p]) {
p = parent[p];
}
return p;
}
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
public void union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) {
return;
}
if (size[pRoot] < size[qRoot]) {
parent[pRoot] = qRoot;
size[qRoot] += size[pRoot];
}
else {
parent[qRoot] = pRoot;
size[pRoot] += size[qRoot];
}
}
}
/**
* @author wangshaoyu
*/
public class POJ1182食物链 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
public static void main(String[] args) throws IOException {
int n = nextInt(); // n 只动物
int k = nextInt(); // k 句话
UnionFind uf = new UnionFind(n * 3);
// 为每只动物设置三个类别 A B C
// 元素 x, x + n, x + n * 2 分别代表 x-A(x属于A类), x-B(x属于B类), x-C(x属于C类)
// 并查集里面的每一个连通分量表示连通分量内所有的元素代表的情况都 同时发生 或者 同时不发生
int ans = 0;
for (int i = 0; i < k; i++) {
int d = nextInt(); // 说话的种类
int x = nextInt() - 1;
int y = nextInt() - 1;
// 超出范围是假话
if (x >= n || y >= n) {
ans++;
continue;
}
// x 和 y 同类
if (d == 1) {
// 如果x是A类,y是B类(也就是判断前面的是否出现了 x 吃 y)
// 如果x是B类,y是C类 和 如果x是C类,y是A类 这两种情况可以不用判断
// 因为如果前面已经出现了x 吃 y,那么这三种情况都会被连通。所以比较一种就可以了
// 或者 前面的描述出现了 x是A类,y是C类,说明 x 和 y 也不可能同类
if (uf.isConnected(x, y + n) || uf.isConnected(x, y + n * 2)) {
ans++;
}
// 将x 和 y 分别都是 A B C 的三种情况连通起来
else {
uf.union(x, y);
uf.union(x + n, y + n);
uf.union(x + n * 2, y + n * 2);
}
}
// x 吃 y
else if (d == 2) {
// 自己吃自己
// x 和 y 是同类
// x是A类,y是C类, 因为A类不吃C类
if (x == y || uf.isConnected(x, y) || uf.isConnected(x, y + n * 2)) {
ans++;
}
else {
uf.union(x, y + n); // A 吃 B
uf.union(x + n, y + n * 2); // B 吃 C
uf.union(x + n * 2, y); // C 吃 A
}
}
}
System.out.println(ans);
}
}