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;
}
上一篇:1.26号英语翻译


下一篇:将两个价格清单放在一行显示