食物链 这道题想了好长时间,也想不明白,看别人的代码又想了好长时间才明白……感觉也不是十分难,但思路不好想。参考http://www.chenyajun.com/2010/02/28/4507 #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <string> #include <cstdio> #include <climits> #include <queue> using namespace std; const int SIZE = 50005; /* 参考吴文虎的讲义,对每个节点,定义一个数组 rank, if rank[i] = 0,说明节点 i 与父节点同类; if rank[i] = 1,说明父节点吃子节点 i; if rank[i] = 2,说明节点 i 吃父节点。 */ int set[SIZE], rank[SIZE]; int find(int x) /* 压缩路径,重新计算节点的 rank */ { int t; if (set[x] == -1) return x; else t = find(set[x]); //试图改成迭代,但没弄出来…… //从根节点往上算 rank[x] = (rank[set[x]] + rank[x]) % 3; set[x] = t; return t; } void uni(int u, int v, int w) { int x, y; x = find(u); y = find(v); set[y] = x; //这个想了半天,其实不难理解。 //v相对x是rank[u]+1,v相对y是rank[v],则设y相对x为t:t + rank[v] = rank[u]+1,然后加3保正就行了 rank[y] = (rank[u] - rank[v] + w + 3) % 3; } int main() { int a, b, c, x, y, n, k; int ans = 0; scanf("%d%d", &n, &k); memset(rank, 0, n*sizeof(int)+10); memset(set, -1, n*sizeof(int)+10); while (k--) { scanf("%d%d%d", &c, &a, &b); if (a > n || b > n) { ans++; continue; } if (c == 2 && a == b) { ans++; continue; } x = find(a); y = find(b); if (x == y) { if (c == 1 && rank[a] != rank[b]) { ans++; continue; } //简单判断1关系 if (c == 2 && (rank[a] + 1) % 3 != rank[b]) { ans++; continue; } } else uni(a, b, c - 1); } printf("%d/n", ans); return 0; }