zoukankan      html  css  js  c++  java
  • poj1741 (点分治)

    Problem Tree

    题目大意

      给一棵树,有边权。求树上距离小于等于K的点对有多少。

    解题分析

      点分治。对每一棵子树进行dfs,求出每棵子树的重心,继而转化为子问题。

      对于经过根的路径i--j,令dep为到根距离,那么需求出dep[i]+dep[j]<=k,且i,j属于不同子树,可以求其补集,求出属于同一子树的对答案贡献。

    参考程序

      1 #include <map>
      2 #include <set>
      3 #include <stack>
      4 #include <queue>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <string>
      8 #include <vector>
      9 #include <cstdio>
     10 #include <cstdlib>
     11 #include <cstring>
     12 #include <cassert>
     13 #include <iostream>
     14 #include <algorithm>
     15 #pragma comment(linker,"/STACK:102400000,102400000")
     16 using namespace std;
     17 
     18 #define N 100008    
     19 #define LL long long
     20 #define lson l,m,rt<<1
     21 #define rson m+1,r,rt<<1|1 
     22 #define clr(x,v) memset(x,v,sizeof(x));
     23 #define bitcnt(x) __builtin_popcount(x)
     24 #define rep(x,y,z) for (int x=y;x<=z;x++)
     25 #define repd(x,y,z) for (int x=y;x>=z;x--)
     26 const int mo  = 1000000007;
     27 const int inf = 0x3f3f3f3f;
     28 const int INF = 2000000000;
     29 /**************************************************************************/ 
     30 
     31 int n,k,sum,tot,root,ans;
     32 int lt[N],f[N],vis[N],size[N],a[N];
     33 struct line{int u,v,w,nt;}eg[N*2];
     34 vector <int> vec;
     35 void add(int u,int v,int w)
     36 {
     37     eg[++sum]=(line){u,v,w,lt[u]};
     38     lt[u]=sum;
     39 }
     40 void init()
     41 {
     42     clr(lt,0); sum=1; ans=0;
     43     clr(f,0); f[0]=INF;
     44     clr(vis,0);
     45 }
     46 void getRoot(int u,int fa)
     47 {    
     48     size[u]=1; f[u]=0;
     49     for (int i=lt[u];i;i=eg[i].nt)
     50     {    
     51         int v=eg[i].v;
     52         if (vis[v] || v==fa) continue;
     53         getRoot(v,u);
     54         size[u]+=size[v];
     55         f[u]=max(f[u],size[v]);
     56     }
     57     f[u]=max(f[u],tot-size[u]);
     58     if (f[u]<f[root]) root=u;
     59 }
     60 void getDeep(int u,int fa)
     61 {
     62     vec.push_back(a[u]);
     63     for (int i=lt[u];i;i=eg[i].nt)
     64     {
     65         int v=eg[i].v;
     66         if (v==fa || vis[v]) continue;
     67         a[v]=a[u]+eg[i].w;
     68         getDeep(v,u);
     69     }
     70 }
     71 int cal(int u,int key)
     72 {
     73     a[u]=key; vec.clear();
     74     getDeep(u,0);
     75     sort(vec.begin(),vec.end());
     76     int tmp=0,l=0,r=vec.size()-1;
     77     while (l<r)
     78     {
     79         if (vec[l]+vec[r]<=k)
     80         {
     81             tmp+=r-l;
     82             l++;
     83         }
     84         else r--;
     85     }
     86     return tmp;
     87 }
     88 void work(int u)
     89 {
     90     ans+=cal(u,0);
     91     vis[u]=1;
     92     for (int i=lt[u];i;i=eg[i].nt)
     93     {
     94         int v=eg[i].v;
     95         if (vis[v]) continue;
     96         ans-=cal(v,eg[i].w);
     97         tot=size[v]; root=0;
     98         getRoot(v,u);
     99         work(root);
    100     }
    101 }
    102 int main()
    103 {
    104     while (~scanf("%d%d",&n,&k))
    105     {
    106         if (n==0) break;
    107         init();
    108         rep(i,1,n-1) 
    109         {
    110             int u,v,w;
    111             scanf("%d%d%d",&u,&v,&w);
    112             add(u,v,w); add(v,u,w);
    113         }
    114         tot=n; root=0;
    115         getRoot(1,0);
    116         work(root);
    117         printf("%d
    ",ans);
    118     }
    119 }
    View Code
  • 相关阅读:
    ACdream HUT新生摸底训练赛 B
    ACdream HUT新生摸底训练赛 A 娜娜梦游仙境系列——诡异的钢琴 水
    Codeforces 534D Handshakes 构造 模拟 贪心
    Codeforces 534C Polycarpus' Dice 构造
    修改优先级(类写法)
    修改优先级(单独事件写法)
    修改完成状态(类写法)
    参数'未开始'没有默认值
    定义类方法过程的时候注意变量参数和实现部分要一致,否则报错无法运行
    修改完成状态(popupmenu菜单二级菜单单击事项)单击独立事件写法
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5922017.html
Copyright © 2011-2022 走看看