点分治的一点理解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点分治的一点理解相关的知识,希望对你有一定的参考价值。

今天菜狗我也学习了一波点分治。

下面是个板子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 20010
using namespace std;
int n,u,v,w,ans,sum,cnt,head[N],f[N],root,sz[N],t[5],d[N];
bool vis[N];
struct node{
    int next,to,dis;
}e[N*20];
void add(int u,int v,int w)
{
    e[++cnt].next=head[u],e[cnt].to=v,e[cnt].dis=w,head[u]=cnt;
}
void getdeep(int u,int fa)
{
    t[d[u]]++;
    for(int i=head[u];i;i=e[i].next)
    {
    int v=e[i].to;
    if(v==fa||vis[v])continue;
    d[v]=(d[u]+e[i].dis)%3;
    getdeep(v,u);
    }
}
int cal(int u,int v)
{
    t[0]=t[1]=t[2]=0;
    d[u]=v;
    getdeep(u,0);
    return t[1]*t[2]*2+t[0]*t[0];
}
void getroot(int u,int fa)
{
    sz[u]=1,f[u]=0;//f数组记录以u为根的最大子树的大小,将最大子树的顶点数最小的点当作分割顶点
    for(int i=head[u];i;i=e[i].next)
    {
    int v=e[i].to;
    if(v==fa||vis[v])continue;//如果vis访问过,表示这个点已经被删掉了
    getroot(v,u);
    sz[u]+=sz[v];
    f[u]=max(f[u],sz[v]);
    }
    f[u]=max(f[u],sum-sz[u]);//以当前树为时还要考虑其父亲的子数大小
    if(f[u]<f[root])root=u;//更新重心
}
void solve(int u)
{
    ans+=cal(u,0);
    vis[u]=1;//将当前点标记
    for(int i=head[u];i;i=e[i].next)
    {
    int v=e[i].to;
    if(vis[v])continue;
    ans-=cal(v,e[i].dis);
    root=0;//初始化根
    getroot(v,0);//找到联通块的重心
    solve(root);//递归下一联通块
    }
}
int gcd(int a,int b)
{
    return !b?a:gcd(b,a%b);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++)scanf("%d%d%d",&u,&v,&w),w%=3,add(u,v,w),add(v,u,w);
    sum=f[0]=n;
    getroot(1,0);//找树的重心
    solve(root);//点分治
    int t=gcd(ans,n*n);
    printf("%d/%d\n",ans/t,n*n/t);
    return 0;
}

 

以上是关于点分治的一点理解的主要内容,如果未能解决你的问题,请参考以下文章

关于Django中间件自己的一点理解

对机器学习的一点理解

关于dijkstra算法的一点理解

"arch/arm/kernel/head.S"里面一点片段的理解

volatile的一点理解

自己关于ES6的一点理解