【模板】点分治

原创 2018年04月15日 19:54:52

传送门:洛谷-【模板】点分治1


题意

给定一棵有n个点的树
询问树上距离为k的点对是否存在。


数据范围

对于30%的数据n<=100
对于60%的数据n<=1000,m<=50
对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000


题解

此题贴板可A。
(题解越来越水了)


代码

#include<bits/stdc++.h>
using namespace std;
const int INF=0x7fffffff;
const int N=1e4+10;
const int K=1e7+10;
typedef long long ll;
int n,x,y,m,MX,tot,root,S,cnt;
int sim[N],head[N],to[N<<1],nxt[N<<1];
ll w[N<<1],c;
ll k,sum[N],mx[N],exi[K],dis[N];
bool vis[N];

inline void lk(int u,int v,ll val)
{
    to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=val;
}

inline void getroot(int now,int f)
{
    sim[now]=1;mx[now]=0;
    for(int i=head[now];i;i=nxt[i]){
        int e=to[i];
        if(vis[e]||(e==f)) continue;
        getroot(e,now);
        sim[now]+=sim[e];
        if(sim[e]>mx[now]) mx[now]=sim[e];
    }
    mx[now]=max(mx[now],(ll)S-sim[now]);
    if(mx[now]<MX){MX=mx[now];root=now;}   
}

inline void query(int now,int f,ll val)
{
    dis[++cnt]=val;
    for(int i=head[now];i;i=nxt[i]){
        int e=to[i];
        if(vis[e]||(e==f)) continue;
        query(e,now,val+w[i]);
    }
}

inline void solve(int now)
{
    cnt=0;
    query(now,0,0);
    for(int i=1;i<cnt;i++){
        for(int j=i+1;j<=cnt;j++){
            exi[dis[i]+dis[j]]++;
        }
    }
}

inline void sol(int now,ll val)
{
    cnt=0;
    query(now,0,val);
    for(int i=1;i<cnt;i++){
        for(int j=i+1;j<=cnt;j++){
            exi[dis[i]+dis[j]]--;
        }
    }
}

inline void divide(int now)
{
    vis[now]=true;solve(now);
    for(int i=head[now];i;i=nxt[i]){
        int e=to[i];
        if(vis[e]) continue;
        sol(e,w[i]);
        S=sim[e];MX=INF;root=0;
        getroot(e,0);
        divide(root);
    }
}

int main(){
    memset(vis,false,sizeof(vis));
    exi[0]=true;
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++){
        scanf("%d%d%lld",&x,&y,&c);
        lk(x,y,c);lk(y,x,c);
    }
    S=n;MX=INF;
    getroot(1,0);
    divide(root);
    while(m--){
        scanf("%d",&k);
        if(exi[k]){
            printf("AYE\n");
        }else{
            printf("NAY\n");
        }
    }
    return 0;
}
版权声明:侵删,转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/79952387

WordPress博客模板系统开发

-
  • 1970年01月01日 08:00

洛谷P3806 【模板】点分治1 【点分治】

题目背景 感谢hzwer的点分治互测。 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在。 输入输出格式 输入格式: n,m 接下来n-...
  • qq_38678604
  • qq_38678604
  • 2017-12-17 10:24:44
  • 176

模板_点分治

struct Node{int v,l;};vector g[N]; int n,k,ans,sz,root,s[N],d[N],f[N]; bool b[N];vector deep; void G...
  • qq_18455665
  • qq_18455665
  • 2016-03-13 14:51:03
  • 250

树分治(点分治模板)poj-1741 Tree

首先讲解一下树分治,以下的内容转自:http://blog.sina.com.cn/s/blog_6d5aa19a0100o73m.html 对于一棵有根树, 树中满足要求的一个数对所对应的一条...
  • u010660276
  • u010660276
  • 2015-04-07 15:22:52
  • 5458

点分治模板 (树中点对距离)

点分治就是在一棵树中,将每个点分治…… 基本概念: 点分治:将一棵无根树变成有根树,再分别处理每棵有根子树。 重心:在一棵树中,这个点的最大子树是所有点中最小的。也可以说是删除该点时,树内剩下的...
  • u011056504
  • u011056504
  • 2016-05-11 20:46:04
  • 853

SPOJ QTREE4 Query on a tree IV(边分治)

qtree
  • u013849646
  • u013849646
  • 2016-03-31 23:29:57
  • 601

hdu 1007 分治法求最小点之间的距离(使用分治法模板)

Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings...
  • winycg
  • winycg
  • 2016-08-12 20:35:43
  • 185

点分治详细解析

点分治,是处理树上路径的一个极好的工具。 一般如果需要大规模处理树上路径,点分治是一个不错的选择。 这里我就来讲一讲我自己对于点分治的一点理解和感悟(帮助新手入坑……) 现在就开始吧!1.点分治...
  • qq_39553725
  • qq_39553725
  • 2017-08-24 21:18:38
  • 878

洛谷 P3806 【模板】点分治1

#include #include #include #define K 10000005 #define N 10005 using std::max; int n,m; int hd[N],nxt...
  • ureaster
  • ureaster
  • 2018-01-06 13:06:48
  • 93

洛谷 P4178 Tree(点分治模板)

点分治用于解决与树上路径有关的统计问题。 点分治的思想类似一般的分治:对于一棵树,一方面处理跨越不同子树的路径,即经过根的路径(相当于分治后合并时考虑跨越不同区间的影响),另一方面递归到各个子树中处...
  • hhz6830975
  • hhz6830975
  • 2018-03-06 13:24:29
  • 14
收藏助手
不良信息举报
您举报文章:【模板】点分治
举报原因:
原因补充:

(最多只允许输入30个字)