[BZOJ1468]Tree 点分治模板

点分治是针对树上路径所提出的算法.
首先先找重心,重心指的是把该点删去使得各连通块大小最大值最小的点.
每一条路径都有且只有两种情况:
1. 经过重心,这里我们直接每次更新deep值,直接算.如果存在某个i,j其到重心的路径有重合,即这是一条非简单路径,那么我们递归子问题然后减去就行,也算是一种容斥吧
2. 不经过重心,直接递归求解了.
BZOJ1468

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 40010
#define inf 0x3f3f3f3f
using namespace std;
struct node{
    int to,wi;
    node*next;
}*con[maxn];
int n,sz[maxn],f[maxn],deep[maxn],de[maxn],sum,tail,root,k,ans;
bool vis[maxn];
void addedge(int x,int y,int w)
{
    node*p=new node;
    p->to=y;
    p->wi=w;
    p->next=con[x];
    con[x]=p;
}
void get_root(int v,int fa)
{
    sz[v]=1;f[v]=0;
    for(node*p=con[v];p;p=p->next)
    if(p->to!=fa&&!vis[p->to]){
        get_root(p->to,v);
        sz[v]+=sz[p->to];
        f[v]=max(f[v],sz[p->to]);
    }
    f[v]=max(f[v],sum-f[v]);
    if(f[v]<f[root]) root=v;
}
void get_dep(int v,int fa)
{
    deep[++tail]=de[v];
    for(node*p=con[v];p;p=p->next)
    if(!vis[p->to]&&p->to!=fa)
        de[p->to]=de[v]+p->wi,get_dep(p->to,v);
}
int cal(int v,int w)
{
    tail=0;de[v]=w;get_dep(v,0);
    int tmp=0;
    sort(deep+1,deep+tail+1);
    for(int l=1,r=tail;l<r;)
    if(deep[l]+deep[r]<=k) tmp+=r-l,l++;
    else r--;
    return tmp;
}
void work(int v)
{
    ans+=cal(v,0);
    vis[v]=1;
    for(node*p=con[v];p;p=p->next)
    if(!vis[p->to]){
        ans-=cal(p->to,p->wi);
        sum=sz[p->to];
        root=0;
        get_root(p->to,root);
        work(root);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;++i)
    {
        int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
        addedge(x,y,w);addedge(y,x,w);
    }
    scanf("%d",&k);
    root=0;sum=n;f[0]=inf;
    get_root(1,0);
    work(root);
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值