zoukankan      html  css  js  c++  java
  • codeforces 165D.Beard Graph 解题报告

    题意:

         给一棵树,树的每条边有一种颜色,黑色或白色,一开始所有边均为黑色,有两个操作:

         操作1:将第i条边变成白色或将第i条边变成黑色。

         操作2 :询问u,v两点之间仅经过黑色变的最短距离。

    树链剖分+树状数组

    学习树链剖分:

    /*
           树链剖分:
           划分轻重链,效果是将一颗树变成了若干段连续的区间。
           向上记录边权
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    
    const int MAX = 111111;
    //子树结点数,所在链链头,同链儿子,结点深度,节点在区间的位置,父节点
    int siz[MAX], top[MAX], son[MAX], dep[MAX], w[MAX], fa[MAX];
    //链式前向星记录一颗树
    struct Edge {
        int v, ne, id;
    } edge[MAX << 1];
    
    int head[MAX], cnt, num;
    int vis[MAX], pos[MAX];;
    //第一次dfs,提取基本信息,划分轻重链
    void Dfs1 (int u, int v) {
        fa[v] = u, dep[v] = dep[u] + 1;
        siz[v] = 1;
        vis[v] = 1;
        int tem = 0, p = -1;
        for (int i = head[v]; i != 0; i = edge[i].ne) {
            int kid = edge[i].v;
            if (!vis[kid]) {
                Dfs1 (v, kid);
                siz[u] += siz[kid];
                if (tem < siz[kid]) tem = siz[kid], p = kid;
            }
        }
        son[v] = p;
    }
    //第二次DFS,将重链映射到区间
    void Dfs2 (int h, int v) {
        top[v] = h;
        w[v] = ++num;
        vis[v] = 1;
        if (son[v] != -1) Dfs2 (h, son[v]);
        for (int i = head[v]; i != 0; i = edge[i].ne) {
            int kid = edge[i].v;
            if (son[v] != kid && !vis[kid])
                Dfs2 (kid, kid);
                  pos[edge[i].id] = w[kid]; //边映射到下结点
        }
    }
    
    void addE (int u, int v, int num) {
        edge[++cnt].v = v, edge[cnt].id = num;
        edge[cnt].ne = head[u], head[u] = cnt;
    }
    
    int A[MAX]; //pos为边的新编号
    void add (int x, int k) {
        for (; x <= num; x += x & -x) A[x] += k;
    }
    int getsum (int x) {
        int s = 0;
        for (; x > 0; x -= x & -x)  s += A[x];
        return s;
    }
    void modify (int x, int k) {
        x = pos[x];
        int sta = getsum (x) - getsum (x - 1);
        if (sta == k) return;
        else add (x, k - sta);
    }
    
    void query (int u, int v) {
        int s = 0, f1 = top[u], f2 = top[v], len = 0;
        while (f1 != f2) {
            if (dep[f1] < dep[f2]) {
                int y = w[v], x = w[f2];
                if (f2 != v) {
                    if (s += getsum (y) - getsum (x) ) break;
                    v = f2;
                    len += y - x;
                }
                if (s += getsum (x) - getsum (x - 1) ) break;
                v = fa[v], f2 = top[v];
                len++;
            }
            else {
                int y = w[u], x = w[f1];
                if (f1 != u) {
                    if (s += getsum (y) - getsum (x) ) break;
                    u = f1;
                    len += y - x;
                }
                if (s += getsum (x) - getsum (x - 1) ) break;
                u = fa[u], f1 = top[u];
                len++;
            }
        }
        int y = w[v], x = w[u];
        s += getsum (max (y, x) ) - getsum (min (y, x) );
        len += abs (y - x);
        printf ("%d
    ", s == 0 ? len : -1);
    }
    int n, u, v, m, t;
    int main() {
        scanf ("%d", &n);
        for (int i = 1; i < n; i++) {
            scanf ("%d %d", &u, &v);
            addE (u, v, i), addE (v, u, i);
        }
        Dfs1 (0, 1);
        memset (vis, 0, sizeof vis);
        Dfs2 (1, 1);
        scanf ("%d", &m);
        int k, l, r,tol=0;
        for (int i = 1; i <= m; i++) {
            scanf ("%d", &k);
            if (k != 3) {
                scanf ("%d", &t);
                modify (t, k == 1 ? 0 : 1);
            }
            if (k == 3) {
                scanf ("%d %d", &l, &r);
                         query (l, r);
            }
    
        }
    }
    View Code
  • 相关阅读:
    Ddr2,ddr3,ddr4内存条的读写速率
    Ddr2,ddr3,ddr4内存条的读写速率
    【VS开发】获取CPU tick tick 周期
    【VS开发】获取CPU tick tick 周期
    【VS开发】malloc申请内存错误分析
    【VS开发】malloc申请内存错误分析
    【VS开发】Return与Exit的区别
    【VS开发】Return与Exit的区别
    【VS开发】C/C++预编译命令
    【VS开发】C/C++预编译命令
  • 原文地址:https://www.cnblogs.com/keam37/p/4004335.html
Copyright © 2011-2022 走看看