• CodeForces 191C Fools and Roads


    题目链接:CodeForces 191C Fools and Roads

    题目大意:
    给定一个\(N\)节点的数,然后有\(M\)次操作,每次从\(u\)移动到\(v\),问说每条边被移动过的次数。

    题解:
    用树上差分来统计,\(u\)走向\(v\),则\(u\)\(v\)之间的路径上的边权都加\(1\),用差分数组表示就是\(diff[u]+1, diff[v]+1, diff[lca(u,v)]-2\)
    注意以点代边的思想。

    #include <iostream>
    using namespace std;
    
    struct Edge {
        int v, next;
    } edge[200010];
    struct Line {
        int x, y;
    } line[100010];
    int cnt, head[100010], depth[100010], fa[100010][25], diff[100010], n, m, ans[100010], id[100010];
    
    void swap(int &x, int &y) {
        x ^= y;
        y ^= x;
        x ^= y;
    }
    
    void addEdge(int u, int v) {
        edge[++cnt].v = v;
        edge[cnt].next = head[u];
        head[u] = cnt;
    }
    
    void dfs(int u, int pre) {
        depth[u] = depth[pre] + 1;
        fa[u][0] = pre;
        for (int i = 1; (1 << i) <= depth[u]; ++i) {
            fa[u][i] = fa[fa[u][i - 1]][i - 1];
        }
        for (int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].v;
            if (v != pre) {
                dfs(v, u);
            }
        }
    }
    
    int lca(int u, int v) {
        if (depth[u] > depth[v]) {
            swap(u, v);
        }
        for (int i = 20; i >= 0; --i) {
            if (depth[u] <= depth[v] - (1 << i)) {
                v = fa[v][i];
            }
        }
        if (u == v) {
            return u;
        }
        for (int i = 20; i >= 0; --i) {
            if (fa[u][i] != fa[v][i]) {
                u = fa[u][i], v = fa[v][i];
            }
        }
        return fa[u][0];
    }
    
    void sum(int u) {
        for (int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].v;
            if (v != fa[u][0]) {
                sum(v);
                diff[u] += diff[v];
            }
        }
        ans[id[u]] = diff[u];
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n;
        for (int i = 1; i < n; ++i) {
            cin >> line[i].x >> line[i].y;
            addEdge(line[i].x, line[i].y);
            addEdge(line[i].y, line[i].x);
        }
        dfs(1, 0);
        for (int i = 1; i < n; ++i) {
            if (depth[line[i].x] > depth[line[i].y]) {
                id[line[i].x] = i;
            } else {
                id[line[i].y] = i;
            }
        }
        cin >> m;
        while (m--) {
            int x, y;
            cin >> x >> y;
            int Lca = lca(x, y);
            diff[x]++;
            diff[y]++;
            diff[Lca] -= 2;
        }
        sum(1);
        for (int i = 1; i < n; ++i) {
            cout << ans[i] << ' ';
        }
        return 0;
    }
    
  • 相关阅读:
    08月24日总结
    08月23日总结
    08月22日总结
    装饰器
    卢菲菲最强大脑记忆训练法全套教程 01
    LeetCode 704 二分查找
    LeetCode 1480 一维数组的动态和
    NIO 总结
    LeetCode 881 救生艇
    url的组成部分
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/15860319.html
Copyright © 2020-2023  润新知