点分治

Posted amitherblogs

tags:

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

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1e4+5;
const int inf=0x3f3f3f3f;
struct edge{
    int v, next;
    int w;
}e[maxn*2];
int head[maxn];
int total=0;
void addedge(int u, int v, int w){
    total++;
    e[total].v=v;
    e[total].w=w;
    e[total].next=head[u];
    head[u]=total;
}
int sim[maxn];//size of the tree i
int mxson[maxn];
int root;
int MX=0;
int Smer;
bool vis[maxn];
void getroot(int u,int fa)
{
    sim[u] = 1; mxson[u] = 0;
    for(int i = head[u];i;i = e[i].next)
        {
          int v = e[i].v;
          if(vis[v]||v == fa)continue;
          getroot(v,u);
          sim[u] = sim[u] + sim[v];
          mxson[u] = max(mxson[u],sim[v]);
        }
      mxson[u] = max(mxson[u],Smer - sim[u]);
    if(mxson[u]<MX){    
          root = u; 
          MX = mxson[u];
    }
}
int dist[maxn];
int ans[10000005];
void query(int& cnt, int u, int fa, int len){//以u为根,树上节点到u的长度 
    dist[++cnt]=len;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(vis[v]||v==fa)continue;
        query(cnt, v, u, e[i].w+len);
    }
}
void solve(int u, int len, int key){
    int cnt=0;
    query(cnt, u, 0, len);
    if(key){
        for(int i=1;i<cnt;i++){
            for(int j=i+1;j<=cnt;j++){
                ans[dist[i]+dist[j]]++;
            }
        }
    }else{
        for(int i=1;i<cnt;i++){
            for(int j=i+1;j<=cnt;j++){
                ans[dist[i]+dist[j]]--;
            }
        }
    }
}
void Divide(int u)
{
  solve(u, 0, 1);//算上所有的 
  vis[u] = true;
  for(int i = head[u];i;i = e[i].next)
    {
      int v = e[i].v;
      if(vis[v])continue;
      solve(v,e[i].w, 0);//减去相同链的 
      Smer = sim[v]; root = 0;MX = inf; getroot(v,0);//get subtree‘s root
      Divide(root);
    }
  return;
}
int main()
{
    freopen("in.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    int cnt=n-1;
    while(cnt--){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    MX=inf;
    Smer=n;
    getroot(1, 0);
    Divide(root);
    while(m--){
        int k;
        scanf("%d",&k);
        if(ans[k])printf("AYE
");
        else printf("NAY
");
    }
}

 

#include<stdio.h>#include<algorithm>#include<iostream>using namespace std;const int maxn=1e4+5;const int inf=0x3f3f3f3f;struct edge{int v, next;int w;}e[maxn*2];int head[maxn];int total=0;void addedge(int u, int v, int w){total++;e[total].v=v;e[total].w=w;e[total].next=head[u];head[u]=total;}int sim[maxn];//size of the tree iint mxson[maxn];int root;int MX=0;int Smer;bool vis[maxn];void getroot(int u,int fa){sim[u] = 1; mxson[u] = 0;for(int i = head[u];i;i = e[i].next)    {      int v = e[i].v;      if(vis[v]||v == fa)continue;      getroot(v,u);      sim[u] = sim[u] + sim[v];      mxson[u] = max(mxson[u],sim[v]);    }  mxson[u] = max(mxson[u],Smer - sim[u]);if(mxson[u]<MX){  root = u;   MX = mxson[u];}}int dist[maxn];int ans[10000005];void query(int& cnt, int u, int fa, int len){//以u为根,树上节点到u的长度 dist[++cnt]=len;for(int i=head[u];i;i=e[i].next){int v=e[i].v;if(vis[v]||v==fa)continue;query(cnt, v, u, e[i].w+len);}}void solve(int u, int len, int key){int cnt=0;query(cnt, u, 0, len);if(key){for(int i=1;i<cnt;i++){for(int j=i+1;j<=cnt;j++){ans[dist[i]+dist[j]]++;}}}else{for(int i=1;i<cnt;i++){for(int j=i+1;j<=cnt;j++){ans[dist[i]+dist[j]]--;}}}}void Divide(int u){  solve(u, 0, 1);//算上所有的   vis[u] = true;  for(int i = head[u];i;i = e[i].next)    {      int v = e[i].v;      if(vis[v])continue;      solve(v,e[i].w, 0);//减去相同链的       Smer = sim[v]; root = 0;MX = inf; getroot(v,0);//get subtree‘s root      Divide(root);    }  return;}int main(){freopen("in.txt","r",stdin);int n,m;scanf("%d%d",&n,&m);int cnt=n-1;while(cnt--){int u,v,w;scanf("%d%d%d",&u,&v,&w);addedge(u,v,w);addedge(v,u,w);}MX=inf;Smer=n;getroot(1, 0);Divide(root);while(m--){int k;scanf("%d",&k);if(ans[k])printf("AYE ");else printf("NAY ");}}

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

基于点分治的树分治

POJ 1741 Tree ——点分治

bzoj2599 [ IOI2011] -- 点分治

算法有关点分治的一些理解与看法

POJ 3714 分治/求平面最近点对

分治——最近点对