BZOJ 3365 Distance Statistics 点分治
这道题是一道点分治的题目,难度不大,可以拿来练手。
关键是对于找出来的重心的删除操作需要删掉这条边,这很重要。
还有每次找重心的时候,不但要考虑他的子节点的siz,还要考虑父节点的siz。
然后就A了。。。
每次点分治 分两种情况讨论一下就可以啦!
/w\...
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 56789; const int INF = 1000000007; int getint() { int r = 0, k = 1; char c; for (c = getchar(); c < '0' || c > '9'; c = getchar() ) if (c == '-') k = -1; for (; '0' <= c && c <= '9'; c = getchar() ) r = r * 10 - '0' + c; return r * k; } int n, m, k; int h[maxn], siz[maxn]; struct edge_type { int v, next, w; bool baned; } edge[maxn * 2]; int tote = 0; void ins(int u, int v, int w) { edge[++tote].v = v; edge[tote].next = h[u]; edge[tote].w = w; edge[tote].baned = false; h[u] = tote; } int fgans, fgsiz; void get_fgans(int now, int fa, int size) { int tmp = 1; siz[now] = 1; for (int i = h[now]; i; i = edge[i].next) { if (!edge[i].baned && fa != edge[i].v) { get_fgans(edge[i].v, now, size); siz[now] += siz[edge[i].v]; if (tmp < siz[edge[i].v]) tmp = siz[edge[i].v]; } } if (tmp < size - siz[now]) tmp = size - siz[now]; if (tmp < fgsiz) { fgans = now; fgsiz = tmp; } } int find_gravity(int rt, int size) { fgsiz = INF; fgans = rt; get_fgans(rt, -1, size); return fgans; } int dis[maxn]; int zhan[maxn], zcnt; void get_dis(int now, int nd, int fa) { dis[now] = nd; for (int i = h[now]; i; i = edge[i].next) if (!edge[i].baned && fa != edge[i].v) get_dis(edge[i].v, nd + edge[i].w, now); } void dfs(int now, int fa) { zhan[++zcnt] = dis[now]; for (int i = h[now]; i; i = edge[i].next) if (!edge[i].baned && fa != edge[i].v) dfs(edge[i].v, now); } int calculate(int rt) { int ret = 0; zcnt = 0; dfs(rt, -1); sort(zhan + 1, zhan + zcnt + 1); for (int i = 1, j = zcnt; i <= zcnt; ++i) { for (; j && zhan[i] + zhan[j] > k; --j); ret += j; } return ret; } int Ans = 0; void dfz(int now, int size) { int rt = find_gravity(now, size); get_dis(rt, 0, -1); Ans += calculate(rt); int v; for (int i = h[rt]; i; i = edge[i].next) if (!edge[i].baned) { edge[i].baned = edge[((i-1)^1)+1].baned = true; Ans -= calculate(edge[i].v); dfz(edge[i].v, siz[edge[i].v]); } } int main() { n = getint(); m = getint(); int u, v, w; for (int i = 1; i < n; ++i) { u = getint(); v = getint(); w = getint(); ins (u, v, w); ins (v, u, w); } k = getint(); dfz(1, n); printf("%d", (Ans - n >> 1)); return 0; }