int findSet(int i){ return (pset[i] == i) ? i : (pset[i] = findSet(pset[i])); }
int findSet(int x){ if(parent[x]==x) return x; return parent[x]=findSet(parent[x]); }
bool isSameSet(int i, int j){ return findSet(i) == findSet(j); }
int rmst(int k) { memset(choose, 0, sizeof(choose)); memset(linkTo, -1, sizeof(linkTo)); makeSet(); sort(edges, edges + m); for (int i = 0; i < m; i++) { if (!edges[i].u) continue; int x = findSet(edges[i].u), y = findSet(edges[i].v); if (x == y) continue; parent[x] = y; choose[i] = 1; } int components = 0; best[0] = INF; for (int i = 1; i < n; i++) if (findSet(i) == i) { components++; best[i] = INF; } if (components > k) return INF; for (int i = 0; i < m; i++) { if (edges[i].u) continue; linkTo[edges[i].v] = i; int x = findSet(edges[i].v); if (edges[i].w < best[x]) { best[x] = edges[i].w; candidate[x] = i; } } for (int i = 1; i < n; i++) if (findSet(i) == i) { if (best[i] == INF) return INF; choose[candidate[i]] = 1; } for (int i = 0; i < n; i++) g[i].clear(); for (int i = 0; i < m; i++) if (choose[i]) addEdge(i); while (components < k) { dfs(-1, 0); int tmpBest = INF, tmpCandidate; for (int i = 1; i < n; i++) { if (linkTo[i] == -1 || best[i] == -INF) continue; int beta = edges[linkTo[i]].w - best[i]; if (beta < tmpBest) { tmpBest = beta; tmpCandidate = i; } } if (tmpBest == INF) return INF; choose[candidate[tmpCandidate]] = 0; choose[linkTo[tmpCandidate]] = 1; addEdge(linkTo[tmpCandidate]); components++; } int sumOfWeight = 0; for (int i = 0; i < m; i++) if (choose[i]) sumOfWeight += edges[i].w; return sumOfWeight; }
void unionSet(int i, int j){ pset[findSet(i)] = findSet(j); }
bool isSameSet (int idxA, int idxB) const { return (findSet(idxA) == findSet(idxB)); }
void Union(SetElement* x, SetElement* y) { link( findSet(x), findSet(y) ) ; }
int findSet(int i) { if(i != p[i]) p[i] = findSet(p[i]); return p[i]; }
int findSet(int x) { if(x != parent[x]) parent[x] = findSet(parent[x]); return parent[x]; }
bool UnionFind::isSameSet(int i, int j) { return (findSet(i) == findSet(j)); }
int UnionFind::sizeOfSet(int i) { return setSize[findSet(i)]; }
//Gets the representative of the element i in the forest f. If two elements return the same value in findSet, they are in the same set int findSet(Forest * f, int i) { if(f->parent[i] != i) f->parent[i] = findSet(f, f->parent[i]); //path compression, speed up future findSets return f->parent[i]; }
void DisjointSets<T>::makeUnion(T* x, T* y) //union the disjoint sets containing data x and y { DSNode<T>* n1 = findSet(x); //find node containing x DSNode<T>* n2 = findSet(y); //find node containing y link(n1, n2); }
JTClique* DisjointSet::findSet(JTClique* i) { if (roots[i] != i) return roots[i] = findSet(roots[i]); return i; }
Vertex* findSet(Vertex* v){ if(v->parent==v) return v; else return findSet(v->parent); }
int main(void) { int m, n, i, j, rel; char str[3], query[2]; while (scanf("%d %d", &n, &m) != EOF) { if (n == 0 && m == 0) break; preProcess(); // 构造并查集 for (i = 0; i < n; i ++) { scanf("%s", str); for (j = 1; j < 3; j ++) { if (str[j] != '-') { parent[str[j] - 'A'] = str[0] - 'A'; } } } for (i = 0; i < m; i ++) { scanf("%s", query); rel = findSet(query[0] - 'A', query[1] - 'A'); if (rel) { switch (rel) { case 1 : printf("parent\n"); break; case 2 : printf("grandparent\n"); break; default : for (j = rel - 2; j > 0; j --) { printf("great-"); } printf("grandparent\n"); break; } } else { rel = findSet(query[1] - 'A', query[0] - 'A'); switch (rel) { case 0 : printf("-\n"); break; case 1 : printf("child\n"); break; case 2 : printf("grandchild\n"); break; default : for (j = rel - 2; j > 0; j --) { printf("great-"); } printf("grandchild\n"); break; } } } } return 0; }
bool diffrentSets(Vertex* v1, Vertex* v2){ return findSet(v1)!=findSet(v2); }
int findSet(int x) { return (parent[x] == x ? x : parent[x] = findSet(parent[x])); }
int operator[] (int idx) const { return findSet(idx); }
int findSet(int x, vector<int> &father) { if(x != father[x]) { father[x] = findSet(father[x], father); } return father[x]; }