POJ-1182
这题挺恶心的,以后再补充
Code
package DisjoinSet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
/**
* 0 同类 1 被父节点吃 2 吃父节点
*/
static int[] rel; // 边权
static int n;
static int[] parent;
static int count;
public static class InputReader {
private BufferedReader in;
private StringTokenizer tokenizer;
public InputReader(InputStream stream) {
in = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(in.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.valueOf(next());
}
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
InputReader reader = new InputReader(System.in);
n = reader.nextInt();
int k = reader.nextInt();
init();
for (int i = 0; i < k; i++) {
int flag = reader.nextInt();
int x = reader.nextInt();
int y = reader.nextInt();
if (x > n || y > n) {// 错误
count++;
continue;
}
if (flag == 2 && x == y) {// 错误
count++;
continue;
}
union(x, y, flag);
}
System.out.println(count);
}
private static void union(int x, int y, int flag) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {// 此时,可以推算出x与y的关系,来判断输入是否有误
if (flag == 1) {
if (!check(x, y)) {
count++;
} // 判断x与y是否为同类关系
} else if (!check2(x, y)) {
count++;
} // 检查是否为x吃y的关系
return;
}
// 此时,x与y所在的集合需要合并
parent[rootY] = rootX;
rel[rootY] = (rel[x] + flag - 1 + 3 - rel[y]) % 3;// !!
}
// 检查是否为x吃y的关系
private static boolean check2(int x, int y) {
if (rel[x] == 0 && rel[y] == 1 || rel[x] == 2 && rel[y] == 0 || rel[x] == 1 && rel[y] == 2)
return true;
return false;
}
// 检查x与y是否是同一种类
private static boolean check(int x, int y) {
if (rel[x] == rel[y])
return true;
return false;
}
private static void init() {
parent = new int[n + 1];
for (int i = 1; i < parent.length; i++) {
parent[i] = i;
}
rel = new int[n + 1];// 初始化为0,代表其与其父节点的关系为同类
count = 0;
}
private static int find(int x) {
if (parent[x] == x)
return parent[x];
int temp = parent[x];// 压缩前的父节点
parent[x] = find(parent[x]);// 压缩
// 维护rel数组
rel[x] = (rel[x] + rel[temp]) % 3;
return parent[x];
}
}