zoukankan      html  css  js  c++  java
  • BZOJ3697: 采药人的路径(点分治)

    Description

    采药人的药田是一个树状结构,每条路径上都种植着同种药材。
    采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
    采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多少种不同的路径。

    Input

    第1行包含一个整数N。
    接下来N-1行,每行包含三个整数a_i、b_i和t_i,表示这条路上药材的类型。

    Output

    输出符合采药人要求的路径数目。

    Sample Input

    7
    1 2 0
    3 1 1
    2 4 0
    5 2 0
    6 3 1
    5 7 1

    Sample Output

    1

    解题思路:

    点分治要求在寻找到一条链时统计答案与重心在链的哪个位置无关。而显然这道题如果枚举重心为中转站是错误的,因为一条链只被统计一次,而中心位置很可能是错误的,所以我们需要修正这一点,就是统计重心路径上可能出现的中心位置。

    换句话说,开四个桶来记录,分别记录当前子树内可能出现的中转站(出现过的距离重复,在差分的意义下说明出现和为0的区间),另外一个就是之前子树的答案,每次更新完合并桶就好了。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 typedef long long lnt;
      5 const int N=100010;
      6 struct pnt{
      7     int hd;
      8     int dis;
      9     int wgt;
     10     bool vis;
     11 }p[N];
     12 struct ent{
     13     int twd;
     14     int lst;
     15     int vls;
     16 }e[N<<1];
     17 lnt f[N<<1][2],g[N<<1][2];
     18 int has[N<<1];
     19 int n;
     20 lnt top;
     21 int cnt;
     22 lnt ans;
     23 int lim;
     24 int size;
     25 int root;
     26 int maxsize;
     27 void ade(int f,int t,int v)
     28 {
     29     cnt++;
     30     e[cnt].twd=t;
     31     e[cnt].lst=p[f].hd;
     32     e[cnt].vls=v;
     33     p[f].hd=cnt;
     34     return ;
     35 }
     36 void grc_dfs(int x,int f)
     37 {
     38     p[x].wgt=1;
     39     int maxs=-1;
     40     for(int i=p[x].hd;i;i=e[i].lst)
     41     {
     42         int to=e[i].twd;
     43         if(to==f||p[to].vis)
     44             continue;
     45         grc_dfs(to,x);
     46         p[x].wgt+=p[to].wgt;
     47         if(p[to].wgt>maxs)
     48             maxs=p[to].wgt;
     49     }
     50     if(maxs<size-p[x].wgt)
     51         maxs=size-p[x].wgt;
     52     if(maxs<maxsize)
     53     {
     54         maxsize=maxs;
     55         root=x;
     56     }
     57     return ;
     58 }
     59 void ans_dfs(int x,int fa,int dep)
     60 {
     61     lim=std::max(lim,dep);
     62     if(has[p[x].dis])
     63         f[p[x].dis][1]++;
     64     else
     65         f[p[x].dis][0]++;
     66     has[p[x].dis]++;
     67     for(int i=p[x].hd;i;i=e[i].lst)
     68     {
     69         int to=e[i].twd;
     70         if(to==fa||p[to].vis)
     71             continue;
     72         p[to].dis=p[x].dis+e[i].vls;
     73         ans_dfs(to,x,dep+1);
     74     }
     75     has[p[x].dis]--;
     76     return ;
     77 }
     78 void bin_dfs(int x)
     79 {
     80     int maxd=0;
     81     p[x].vis=true;
     82     g[n][0]=1;
     83     for(int i=p[x].hd;i;i=e[i].lst)
     84     {
     85         int to=e[i].twd;
     86         if(p[to].vis)
     87             continue;
     88         p[to].dis=n+e[i].vls;
     89         lim=1;
     90         ans_dfs(to,to,1);
     91         maxd=std::max(maxd,lim);
     92         ans+=f[n][0]*(g[n][0]-1);
     93         for(int j=-lim;j<=lim;j++)
     94             ans+=g[n-j][1]*f[n+j][1]+g[n-j][1]*f[n+j][0]+g[n-j][0]*f[n+j][1];
     95         for(int j=n-lim;j<=n+lim;j++)
     96         {
     97             g[j][0]+=f[j][0];
     98             g[j][1]+=f[j][1];
     99             f[j][0]=f[j][1]=0;
    100         }
    101     }
    102     for(int i=n-maxd;i<=n+maxd;i++)
    103         g[i][0]=g[i][1]=0;
    104     for(int i=p[x].hd;i;i=e[i].lst)
    105     {
    106         int to=e[i].twd;
    107         if(p[to].vis)
    108             continue;
    109         root=0;
    110         size=p[to].wgt;
    111         maxsize=0x3f3f3f3f;
    112         grc_dfs(to,to);
    113         bin_dfs(root);
    114     }
    115     return ;
    116 }
    117 int main()
    118 {
    119     scanf("%d",&n);
    120     for(int i=1;i<n;i++)
    121     {
    122         int a,b,c;
    123         scanf("%d%d%d",&a,&b,&c);
    124         c=c*2-1;
    125         ade(a,b,c);
    126         ade(b,a,c);
    127     }
    128     root=0;
    129     size=n;
    130     maxsize=0x3f3f3f3f;
    131     grc_dfs(1,1);
    132     bin_dfs(root);
    133     printf("%lld
    ",ans);
    134     return 0;
    135 }
  • 相关阅读:
    python 表达式
    anaconda jupyter notebook 启动方法
    python3基本数据类型补充
    Python3 基本数据类型
    pycharm 与 anaconda 关联
    31.Android之常用单位px、dip、sp学习
    30.Android之百度地图简单学习
    29.Android之文本框输入自动提示学习
    28.Android之权限请求汇总
    27.Android之ImageView获取图片学习
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10159463.html
Copyright © 2011-2022 走看看