点分治模板

POJ-1741

//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 10005;
int head[maxn],To[maxn<<2],Next[maxn<<2],len[maxn<<2],vis[maxn],dis[maxn];
int sz[maxn],mxson[maxn],Mx,root;
int n,k,ans,cnt,N,tot;
void add(int u,int v,int w){
    Next[++cnt]=head[u];
    head[u]=cnt;
    To[cnt]=v;
    len[cnt]=w;
}
void getroot(int u,int fa){
    sz[u]=1;mxson[u]=0;
    for(int i=head[u];i;i=Next[i]){
        int v=To[i];
        if(v==fa||vis[v]) continue;
        getroot(v,u);
        sz[u]+=sz[v];
        mxson[u]=max(mxson[u],sz[v]);
    }
    mxson[u]=max(mxson[u],N-sz[u]);
    if(mxson[u]<Mx){
        root=u;
        Mx=mxson[u];
    }
}
void getdis(int u,int fa,int d){
    dis[++tot]=d;
    for(int i=head[u];i;i=Next[i]){
        int v=To[i];
        if(vis[v]||v==fa) continue;
        getdis(v,u,d+len[i]);
    }
}
int solve(int u,int d){
    tot=0;
    memset(dis,0,sizeof(dis));
    getdis(u,0,d);
    sort(dis+1,dis+1+tot);
    int l=1;int r=tot;int res=0;
    while(l<=r){
        if(dis[r]+dis[l]<=k){
            res+=r-l;
            l++;
        }else r--;
    }
    return res;
}
void Divide(int u){
    ans+=solve(u,0);
    vis[u]=1;
    for(int i=head[u];i;i=Next[i]){
        int v=To[i];
        int d=len[i];
        if(vis[v]) continue;
        ans-=solve(v,d);
        N=sz[v];root=0;Mx=INF;
        getroot(v,0);
        Divide(root);
    }
}
int main(){
    while(~scanf("%d %d",&n,&k)){
        if(n==0&&k==0) break;
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        cnt=0;
        N=n;
        for(int i=1;i<n;i++){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        ans=0;
        Mx=INF;
        getroot(1,0);
        Divide(root);
        cout<<ans<<"
";
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/MengX/p/11172834.html