P4178 Tree

最简单的点分治

淀粉质的思想:

“分而治之”,缩小问题规模,合并求解;

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 using namespace std;
  7 #define up(i,l,r) for(register int i = (l); i <= (r); ++i)
  8 #define dn(i,l,r) for(register int i = (l); i >= (r); --i)
  9 #define ll long long
 10 #define re register
 11 using namespace std;
 12 
 13 template <typename T> void in(T &x) {
 14     x = 0; T f = 1; char ch = getchar();
 15     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
 16     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
 17     x *= f;
 18 }
 19 
 20 template <typename T> void out(T x) {
 21     if(x < 0) x = -x , putchar('-');
 22     if(x > 9) out(x/10);
 23     putchar(x%10 + 48);
 24 }
 25 //---------------------------------------------------------
 26 
 27 const int N = 40007;
 28 
 29 struct edge {
 30     int v,w,nxt;
 31 } e[N<<1];int tot,head[N];
 32 
 33 void add(int u,int v,int w) {
 34     e[++tot].v = v;
 35     e[tot].w = w;
 36     e[tot].nxt = head[u];
 37     head[u] = tot;
 38 }
 39 //---------------------------------------------------------
 40 
 41 int n,k,ans;
 42 int size[N];
 43 int Tsize,cnt,rt;
 44 int cdis[N],dis[N];
 45 bool vis[N];
 46 
 47 int f[N];
 48 void get_rt(int u,int fa) {
 49     size[u] = 1; f[u] = 0;
 50     for(re int i = head[u]; i; i = e[i].nxt) {
 51         int v = e[i].v; if(v == fa || vis[v]) continue;
 52         get_rt(v,u);
 53         size[u] += size[v];
 54         f[u] = max(size[v],f[u]);
 55     }
 56     f[u] = max(f[u],Tsize-size[u]);
 57     if(f[u] < f[rt]) rt = u;
 58 }
 59 
 60 void get_dis(int u,int fa) {
 61     cdis[++cnt] = dis[u];
 62     for(re int i = head[u]; i; i = e[i].nxt) {
 63         int v = e[i].v; if(v == fa || vis[v]) continue;
 64         dis[v] = dis[u] + e[i].w; get_dis(v,u);
 65     }
 66 }
 67 
 68 int calc(int u) {
 69     cnt = 0,get_dis(u,0);
 70     sort(cdis+1,cdis+cnt+1);
 71     int l = 1,r = cnt,sum = 0;
 72     while(l < r) {
 73         if(cdis[l] + cdis[r] <= k) sum += r-l,++l;
 74         else --r; 
 75     }
 76     return sum;
 77 }
 78 
 79 void new_tree(int u) {
 80     vis[u] = 1; dis[u] = 0;//
 81     ans += calc(u);
 82     for(re int i = head[u]; i; i = e[i].nxt) {
 83         int v = e[i].v; if(vis[v]) continue;
 84         dis[v] = e[i].w;//
 85         ans -= calc(v);
 86         rt = 0,Tsize = size[v];
 87         get_rt(v,0); new_tree(rt);
 88     }
 89 } 
 90 
 91 
 92 void init() {
 93     memset(head,0,sizeof(head));
 94     memset(vis,0,sizeof(vis));
 95     Tsize = n,rt = 0,f[0] = n+1; ans = 0;
 96 }
 97 
 98 int main() {
 99     freopen("input.txt","r",stdin);
100     in(n);
101     init(); int x,y,w;
102     up(i,1,n-1) in(x),in(y),in(w),add(x,y,w),add(y,x,w);in(k);
103     get_rt(1,0); new_tree(rt);
104     out(ans); putchar('\n');
105 }

 

posted @ 2019-04-19 17:06  陈星卿  阅读(90)  评论(0编辑  收藏  举报