[BZOJ 3365] Distance Statistics
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3365
[算法]
点分治
[代码]
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXN 40010 int i,n,m,k,tot,len,ans,root,u,v,w; int head[MAXN],weight[MAXN],size[MAXN],d[MAXN],dep[MAXN]; bool visited[MAXN]; char c; struct Edge { int to,w,nxt; } e[MAXN<<1]; inline void addedge(int u,int v,int w) { tot++; e[tot] = (Edge){v,w,head[u]}; head[u] = tot; } inline void get_root(int u,int fa,int total) { int i,v; size[u] = 1; weight[u] = 0; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (v != fa && !visited[v]) { get_root(v,u,total); size[u] += size[v]; weight[u] = max(weight[u],size[v]); } } weight[u] = max(weight[u],total-size[u]); if (weight[u] < weight[root]) root = u; } inline void dfs(int u,int fa) { int i,v,w; d[++len] = dep[u]; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v] && v != fa) { dep[v] = dep[u] + w; dfs(v,u); } } } inline int calc(int u) { int i,j; int ret = 0; len = 0; dfs(u,0); i = 1; j = len; sort(d+1,d+len+1); while (i < j) { if (d[i] + d[j] <= k) { ret += j - i; i++; } else j--; } return ret; } inline void work(int u) { int i,v,w; dep[u] = 0; visited[u] = true; ans += calc(u); for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v]) { dep[v] = w; ans -= calc(v); root = 0; get_root(v,0,size[v]); work(root); } } } int main() { scanf("%d%d",&n,&m); memset(visited,false,sizeof(visited)); tot = 0; for (i = 1; i <= n; i++) head[i] = 0; for (i = 1; i < n; i++) { scanf("%d%d%d %c",&u,&v,&w,&c); addedge(u,v,w); addedge(v,u,w); } scanf("%d",&k); size[0] = weight[0] = n; root = 0; get_root(1,0,0); ans = 0; work(root); printf("%d\n",ans); return 0; }