首页 > 代码库 > 并查集

并查集

POJ 1182 食物链

添加一个维护当前节点与父节点关系的信息,每次压缩时更新关系,另外join的时候也要根据当前节点和父节点关系以及两个父节点关系更新;

单case,不用EOF处理。

# include <cstdio>const int maxn = 50005;int n, k;int p[maxn];int g[maxn];int find(int x) {    if (x == p[x]) return x;    int t = find(p[x]);    g[x] = ((g[p[x]] + g[x]) % 3 + 3) % 3;    p[x] = t;    return t;}# define testin freopen("in.txt", "r", stdin)int main(){    //while (scanf("%d%d", &n, &k) != EOF) {        scanf("%d%d", &n, &k);        for (int i = 1; i <= n; ++i) p[i] = i, g[i] = 0;        int ans = 0;        for (int i = 0, od, x, y; i < k; ++i) {            scanf("%d%d%d", &od, &x, &y);            if (x>n||y>n || (od==2 && x==y)) {                ++ans;                continue;            } else {                int fx = find(x);                int fy = find(y);                if (fx != fy) {                    p[fx] = fy;                    g[fx] = ((g[y]-g[x]+od-1)%3+3)%3;                } else if (((g[x]-g[y])%3+3)%3 != od-1){                    ++ans;                }            }        }        printf("%d\n", ans);    //}    return 0;}

 

HDU 2473

带删除节点的并查集

对每个节点,映射射到一个虚拟节点,然后对虚拟节点维护并查集,删除节点时,将对应节点应射到一个新的节点即可,由于查询次数有限,浪费的空间可以接受。

# include <cstdio>const int maxn = 100005;const int maxm = 1000005;int n, m;int fa[maxn + maxm];bool isRoot[maxn + maxm];int link[maxn];int id;int find(int x) {    if (x != fa[x]) return fa[x]=find(fa[x]);}void join(int x, int y){    x = find(x);    y = find(y);    if (x != y) fa[x] = y;}void del(int x){    link[x] = id++;}# define testin freopen("in.txt", "r", stdin)int main(){    int ica = 0;    while (scanf("%d%d", &n, &m), n||m) {        for (int i = 0; i < n+m; ++i) isRoot[i]=false, fa[i]=i;        for (int i = 0; i < n; ++i) link[i] = i;        char od[5];        id = n;        for (int i = 0, x, y; i < m; ++i) {            scanf("%s%d", od, &x);            if (od[0] == M) {                scanf("%d", &y);                join(link[x], link[y]);            } else {                del(x);            }        }        int ans = 0;        for (int i = 0; i < n; ++i) {            if (!isRoot[ find(link[i]) ]) {                ++ans;                isRoot[ find(link[i]) ] = true;            }        }        printf("Case #%d: %d\n", ++ica, ans);    }    return 0;}

 

ZOJ 3261

带删除边的并查集。

WA:维护的并不是树,每个节点和多个节点直接有关系,不能直接删除并查集中的边。

并查集