zoukankan      html  css  js  c++  java
  • POJ 1741 单次询问树上距离<=K的点对数 点分治

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN = 1e5 + 5;
    const int MAXM = 1e5 + 5;
    int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], ed = 1;
    int cost[MAXM << 1];
    inline void addedge(int u, int v, int c) {
            to[++ed] = v;
            cost[ed] = c;
            nxt[ed] = Head[u];
            Head[u] = ed;
    }
    inline void ADD(int u, int v, int c) {
            addedge(u, v, c);
            addedge(v, u, c);
    }
    int n, k, anser;
    int sz[MAXN], f[MAXN], dep[MAXN], sumsz, root;
    bool vis[MAXN];
    int o[MAXN], cnt;
    void getroot(int x, int fa) {
            sz[x] = 1;
            f[x] = 0;
            for (int i = Head[x]; i; i = nxt[i]) {
                    int v = to[i];
                    if (v == fa || vis[v]) {
                            continue;
                    }
                    getroot(v, x);
                    sz[x] += sz[v];
                    f[x] = max(f[x], sz[v]);
            }
            f[x] = max(f[x], sumsz - sz[x]);
            if (f[x] < f[root]) {
                    root = x;
            }
    }
    void getdeep(int x, int fa) {
            o[++cnt] = dep[x];
            for (int i = Head[x]; i; i = nxt[i]) {
                    int v = to[i];
                    if (v == fa || vis[v]) {
                            continue;
                    }
                    dep[v] = dep[x] + cost[i];
                    getdeep(v, x);
            }
    }
    int calc(int x, int d) {
            cnt = 0;
            dep[x] = d;
            getdeep(x, 0);
            sort(o + 1, o + cnt + 1);
            int l = 1, r = cnt, ansnow = 0;
            while (l < r) {
                    if (o[l] + o[r] <= k) {
                            ansnow += r - l, l++;
                    } else {
                            r--;
                    }
            }
            return ansnow;
    }
    void solve(int x) {
            anser += calc(x, 0); //满足Depth(i)+Depth(j)<=k的对数
            vis[x] = 1;
            int totsz = sumsz;
            for (int i = Head[x]; i; i = nxt[i]) {
                    int v = to[i];
                    if (vis[v]) {
                            continue;
                    }
                    anser -= calc(v, cost[i]);//满足Depth(i)+Depth(j)<=k且Belong(i)=Belong(j)的对数
                    root = 0;
                    sumsz = sz[v] > sz[x] ? totsz - sz[x] : sz[v];
                    getroot(v, 0);
                    solve(root);
            }
    }
    int main() {
            while (scanf("%d %d", &n, &k) && (n + k)) {
                    cnt = anser = 0;
                    memset(Head, 0, sizeof(Head));
                    memset(vis, 0, sizeof(vis));
                    ed = 1;
                    int u, v, c;
                    for (int i = 1; i < n; i++) {
                            scanf("%d %d %d", &u, &v, &c);
                            ADD(u, v, c);
                    }
                    root = 0, sumsz = f[0] = n;
                    getroot(1, 0);
                    solve(root);
                    printf("%d
    ", anser);
            }
            return 0;
    }
    View Code
  • 相关阅读:
    shiro
    leetcode696 C++ 36ms 计算二进制子串
    leetcode557 C++ 56ms 反转字符串中的每个单词
    leetcode657 C++ 16ms 判断回环
    leetcode709 C++ 4ms 转换成小写字母
    leetcode141 C++ 8ms 环形链表
    leetcode160 C++ 32ms 相交链表
    leetcode234 C++ 28ms 回文链表
    leetcode203 C++ 28ms 删除链表中满足条件的节点
    leetcode83 C++ 12ms 删除有序链表中的重复元素
  • 原文地址:https://www.cnblogs.com/Aragaki/p/10473982.html
Copyright © 2011-2022 走看看