zoukankan      html  css  js  c++  java
  • LOJ10131. 「一本通 4.4 例 2」暗的连锁【树上差分】

    LINK


    solution

    很简单的题

    你就考虑实际上是对每一个边求出两端节点分别在两个子树里面的附加边的数量

    然后这个值是0第二次随便切有m种方案,如果这个值是1第二次只有一种方案

    如果这个值是2或者更大没有方案

    然后就可以直接统计答案了

    那么就对每一次查询的边

    在两个节点++,lca处-2就可以了


    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 10;
    struct Edge {
      int v, nxt;
    } E[N << 1];
    int n, m, ans = 0;
    int dep[N], head[N], tot = 0;
    int tag[N], fa[N][20];
    
    void add(int u, int v) {
      E[++tot] = (Edge) {v, head[u]};
      head[u] = tot;
    }
    
    void dfs(int u, int father) {
      dep[u] = dep[father] + 1;
      fa[u][0] = father;
      for (int i = 1; i <= 18; i++)
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
      for (int i = head[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (v == father) continue;
        dfs(v, u);
      }
    }
    
    int LCA(int u, int v) {
      if (dep[u] < dep[v]) swap(u, v);
      int delta = dep[u] - dep[v];
      for (int i = 18; i >= 0; i--) {
        if ((delta >> i) & 1) {
          u = fa[u][i];
        }
      }
      if (u == v) return u;
      for (int i = 18; i >= 0; i--) {
        if (fa[u][i] != fa[v][i]) {
          u = fa[u][i];
          v = fa[v][i];
        }
      }
      return fa[u][0];
    }
    
    int solve(int u, int father) {
      int sum = tag[u];
      for (int i = head[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (v == father) continue;
        int w = solve(v, u);
        if (w == 1) ans++;
        if (w == 0) ans += m;
        sum += w;
      }
      return sum;
    }
    int main() {
    #ifdef dream_maker
      freopen("input.txt", "r", stdin);
    #endif
      scanf("%d %d", &n, &m);
      for (int i = 2; i <= n; ++i) {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v);
        add(v, u);
      }
      dfs(1, 0);
      for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d %d", &u, &v);
        tag[u]++;
        tag[v]++;
        tag[LCA(u, v)] -= 2;
      }
      solve(1, 0);
      printf("%d", ans);
      return 0;
    }
    
  • 相关阅读:
    禁止在工作流设计器启动持续活动的重新编译
    设计流程 工作流
    workflow 工作流
    访问调度控制 时间控件
    如何:实现一个视图项目
    Python多线程之threading.Thread实现
    gcc 编译流程分析
    如何编写Makefile?
    linux 文件夹的颜色代表什么意思
    STL容器的迭代器失效的原因
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9917185.html
Copyright © 2011-2022 走看看