BZOJ3319: 黑白树 并查集乱搞

版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82382446

Description
给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:
1.查询u到根路径上的第一条黑色边的标号。
2.将u到v 路径上的所有边的颜色设为黑色。
Notice:这棵树的根节点为1


Sample Input
5 4
1 2
1 3
2 4
2 5
1 2
2 2 3
1 3
1 4


Sample Output
0
2
1


好像挺容易想的。。。
先把黑色染完,然后将白边相连的点并到最深节点的并查集中。
然后反着做对于每一个染黑操作,就相当于把他染白。
然后每次染黑记录他染掉的边的编号即可。
vector好像有点慢,于是写了个链表。
时间好像OJ第二,嘻嘻


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int read() {
    int s = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * f;
}
int put(int x) {
    if(x == 0) putchar('0');
    int num = 0; char c[15];
    while(x) c[++num] = x % 10 + '0', x /= 10;
    while(num) putchar(c[num--]);
    puts("");
}

struct node {
    int x, y, opt;
} a[1100000];
struct edge {
    int x, y, c, next;
} e[2100000]; int len, last[1100000];
int dep[1100000], fa[1100000], f[1100000], id[1100000], ans[1100000], ff[1100000];
bool v[1100000], mark[1100000];
int head[1100000], next[1100000];

void ins(int x, int y, int c) {
    e[++len].x = x; e[len].y = y; e[len].c = c;
    e[len].next = last[x]; last[x] = len;
}

int findfa(int x) {
    if(f[x] != x) f[x] = findfa(f[x]);
    return f[x];
}

int findfa2(int x) {
    if(ff[x] != x) ff[x] = findfa2(ff[x]);
    return ff[x];
}

void dfs(int x) {
    f[x] = x;
    for(int k = last[x]; k; k = e[k].next) {
        int y = e[k].y;
        if(y != fa[x]) id[y] = e[k].c, dep[y] = dep[x] + 1, fa[y] = x, dfs(y);
    }
}

void Merge(int x, int y, int i) {
    x = findfa(x), y = findfa(y);
    int last = -1; head[i] = last;
    while(x != y) {
        if(dep[x] < dep[y]) swap(x, y);
        int fx = findfa(fa[x]);
        f[x] = fx; if(last == -1) head[i] = x, last = x;
        else next[last] = x, last = x;
        x = fx;
    } v[x] = 1; next[last] = -1;
}

void dfs2(int x) {
    for(int k = last[x]; k; k = e[k].next) {
        int y = e[k].y;
        if(y != fa[x]) {
            if(findfa(x) != findfa(y)) {
                int fx = findfa2(x);
                ff[y] = fx;
            } dfs2(y);
        }
    }
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i = 1; i < n; i++) {
        a[i].x = read(), a[i].y = read();
        ins(a[i].x, a[i].y, i + 1), ins(a[i].y, a[i].x, i + 1);
    } id[1] = 1; dfs(1);
    for(int i = 1; i <= m; i++) {
        a[i].opt = read();
        if(a[i].opt == 2) a[i].x = read(), a[i].y = read(), Merge(a[i].x, a[i].y, i);
        else a[i].x = read();
    } for(int i = 1; i <= n; i++) ff[i] = i;
    dfs2(1);
    for(int i = m; i; i--) {
        if(a[i].opt == 2) {
            int x = head[i];
            while(x != -1) {
                int fx = findfa2(fa[x]);
                ff[x] = fx;
                x = next[x];
            }
        } else ans[i] = findfa2(a[i].x);
    } for(int i = 1; i <= m; i++) if(a[i].opt == 1) put(id[ans[i]] - 1);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xgc_woker/article/details/82382446
今日推荐