码迷,mamicode.com
首页 > 其他好文 > 详细

POJ1741(点分治)

时间:2019-05-04 09:29:52      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:scan   init   turn   点分治   cal   algorithm   std   head   ace   

分治的时候SZ感觉是错的……但是貌似第一次找好重心就够了,之后SZ别太离谱就不会T,重心随一随缘就好……

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1e4 + 5;
int n, k, mx, SZ, ans;
struct Edge {
    int to, nxt, cost;
}e[maxn << 2];
int head[maxn], tot, size[maxn], root, dis[maxn], vis[maxn];
int l, r, Q[maxn];

void add(int u, int v, int c) {
    e[++tot].to = v, e[tot].cost = c, e[tot].nxt = head[u], head[u] = tot;
}

void GetRoot(int cur, int fa) {
    int tmp = 0;
    size[cur] = 1;
    for (int i = head[cur]; i; i = e[i].nxt) {
        int son = e[i].to;
        if (son == fa || vis[son])  continue;
        GetRoot(son, cur);
        size[cur] += size[son];
        tmp = max(tmp, size[son]);
    }
    tmp = max(tmp, SZ - size[cur]);
    if (tmp < mx)   mx = tmp, root = cur;
}

void GetDis(int cur, int fa) {
    Q[++r] = dis[cur];
    for (int i = head[cur]; i; i = e[i].nxt) {
        int son = e[i].to;
        if (son == fa || vis[son])  continue;
        dis[son] = dis[cur] + e[i].cost;
        GetDis(son, cur);
    }
}

int calc(int cur, int val) {
    l = 1, r = 0;
    dis[cur] = val;
    GetDis(cur, 0);
    sort(Q + 1, Q + 1 + r);
    int res = 0;
    while (l < r) {
        if (Q[l] + Q[r] <= k)   res += r - l, l++;
        else    r--;
    }
    return res;
}

void divide(int cur) {
    ans += calc(cur, 0);
    vis[cur] = 1;
    for (int i = head[cur]; i; i = e[i].nxt) {
        int son = e[i].to;
        if (vis[son])   continue;
        ans -= calc(son, e[i].cost);
        mx = 2e9, SZ = size[son];
        GetRoot(son, 0);
        divide(root);
    }
}

void init() {
    ans = 0, tot = 0, mx = 2e9, SZ = n;
    for (int i = 1; i <= n; i++)    head[i] = 0, vis[i] = 0;
}

int main() {
    while (scanf("%d %d", &n, &k) == 2 && (n | k)) {
        init();
        for (int u, v, cost, i = 1; i < n; i++) {
            scanf("%d %d %d", &u, &v, &cost);
            add(u, v, cost), add(v, u, cost);
        }
        GetRoot(1, 0);
        divide(root);
        printf("%d\n", ans);
    }
    return 0;
}

POJ1741(点分治)

标签:scan   init   turn   点分治   cal   algorithm   std   head   ace   

原文地址:https://www.cnblogs.com/AlphaWA/p/10807258.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!