【usaco 2013 open】【JZOJ 3234】 阴阳

Description

给出一棵树。树的边权为1或-1。现在要求有多少个点对 (u,v) 满足,存在中间点 k(ku,v) dis[u,k]=0 dis[k,v]=0 dis[u,v] 表示从 u v的最短路径上的边权和。

Analysis

求树上点对数的题目一般都用点分治解决。这题亦是如此,当作是点分治的练习。
这题大概要把合法点对分成三类:

  1. 路径经过根节点(其中,根节点作为中间点还要特殊考虑)
  2. 根节点为一条路径的端点
  3. 整个路径都在子树里面

第3点直接沿着子树递归下去即可。
第2点特判一下直接计入答案。关键是第一点。
首先把 dis[v] (表示 v 到当前重心的dis)和p[v](表示 dis[v] v 的祖先中是否出现过)一边dfs求出。
然后满足p[v]=true的点和其他点算路径时满足有合法的中间点在 (v,root) 上。基于这个思想,再分类讨论一下即可。这题的细节非常多,能一次 AC 的都是大神。

Key Code

    fo(i,1,num)
    {
        if(a[i].p && a[i].w==0) ans++;
        lyd[N+a[i].w][a[i].p]++;
    }
    ll x=0;
    top=a[num+1].bz=0;
    if(num)
    fo(i,1,num+1)
    {
        if(a[i].bz!=a[i-1].bz)
        {
            fo(k,1,top)
            {
                if(type[k]) x+=lyd[q[k]][0]+lyd[q[k]][1]-d[q[k]][0]-d[q[k]][1];
                else x+=lyd[q[k]][1]-d[q[k]][1];
            }
            for(;top;top--)
                d[q[top]][0]=d[q[top]][1]=d[N+N-q[top]][0]=d[N+N-q[top]][1]=0;
            if(i>num) break;
        }
        q[++top]=N-a[i].w,type[top]=a[i].p;
        d[N+a[i].w][a[i].p]++;
        if(a[i].w==0) type[top]=1;
    }
    ans+=x/2;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值