POJ1741

树分治,每次把每个点的deep取出,排序。。。尺取法。。。

# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <algorithm>
# include <string.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;

IL ll Read(){
    RG char c = getchar(); RG ll x = 0, z = 1;
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + c - '0';
    return x * z;
}

const int MAXN(20010), INF(2147483647);
int n, cnt, fst[MAXN], to[MAXN], nxt[MAXN], w[MAXN], k;
int size[MAXN], rt, sz, mx[MAXN], vis[MAXN];
ll ans, d[MAXN];

IL void Add(RG int u, RG int v, RG int f){  nxt[cnt] = fst[u]; to[cnt] = v; w[cnt] = f; fst[u] = cnt++;  }

IL void Getroot(RG int u, RG int fa){
    size[u] = 1; mx[u] = 0;
    for(RG int e = fst[u]; e != -1; e = nxt[e]){
        if(vis[to[e]] || to[e] == fa) continue;
        Getroot(to[e], u);
        size[u] += size[to[e]];
        mx[u] = max(mx[u], size[to[e]]);
    }
    mx[u] = max(mx[u], sz - size[u]);
    if(mx[u] < mx[rt]) rt = u;
}


IL void Getdeep(RG int u, RG int fa, RG ll dis){
    d[++cnt] = dis;
    for(RG int e = fst[u]; e != -1; e = nxt[e]){
        if(vis[to[e]] || to[e] == fa) continue;
        Getdeep(to[e], u, dis + w[e]);
    }
}

IL ll Calc(RG int u, RG int f){
    cnt = 0; Getdeep(u, 0, f);
    sort(d + 1, d + cnt + 1);
    RG ll ret = 0, l = 1, r = cnt;
    while(l < r) if(d[r] + d[l] <= k) ret += r - l, l++; else r--;
    return ret;
}

IL void Solve(RG int u){
    ans += Calc(u, 0); vis[u] = 1;
    for(RG int e = fst[u]; e != -1; e = nxt[e]){
        if(vis[to[e]]) continue;
        ans -= Calc(to[e], w[e]);
        rt = 0; sz = size[to[e]];
        Getroot(to[e], u);
        Solve(rt);
    }
}

int main(RG int argc, RG char* argv[]){
    n = Read(); k = Read(); mx[0] = INF;
    while(n && k){
        Fill(fst, -1); Fill(vis, 0); rt = ans = cnt = 0; sz = n;
        for(RG int i = 1, u, v, f; i < n; i++) u = Read(), v = Read(), f = Read(), Add(u, v, f), Add(v, u, f);
        Getroot(1, 0); Solve(rt);
        printf("%lld
", ans);
        n = Read(); k = Read();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjoieryl/p/8206385.html