P3806 【模板】点分治1

模板题 P3806 【模板】点分治1

题目描述

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

详讲

关于点分治具体内容可以看这个
这里主要是详细讲讲代码:
getrt是用来求重心,我们利用树型dp的思维来做,即找到该节点所有的子树,找到最大的哪一颗即可

void getrt(int u,int pa)//求重心 
{size[u]=1; maxp[u]=0;for(int i=head[u];i;i=E[i].nxt) {int v=E[i].v;if(v==pa||vis[v]) continue;getrt(v,u);size[u]+=size[v];maxp[u]=max(maxp[u],size[v]);}maxp[u]=max(maxp[u],sum-size[u]);if(maxp[u]<maxp[rt]) rt=u;
}

getdis是用来求每一个子节点到根的距离
getdis在calc中不断被调用

void getdis(int u,int fa)//每一个子节点到根的距离 
{rem[++rem[0]]=dis[u];for(int i=head[u];i;i=E[i].nxt){int v=E[i].v;if(v==fa||vis[v])continue;dis[v]=dis[u]+E[i].dis;getdis(v,u);}
}

calc是用来合并答案的,因为在getdis中已经计算出所有点到根的距离,所以把任意两个出现的距离凑在一起,并】、判断可否凑出我们需要的k即可
rem[i]存的是在getdis中求出的距离,rem[0]这个值是值rem存了多少值
judge我们可以用来存距离,对已经出现的距离用judge标记为1,这样当出现另一个距离可以和这个距离搭配成我们所需的k时,就可以直接标记答案
judge[query[k]-rem[j]];
query[k]-rem[j]即为所需要的距离

test[k]|=judge[query[k]-rem[j]];
用|就可以实现如果有就给test标记

void calc(int u)
{int p=0;for(int i=head[u];i;i=E[i].nxt){int v=E[i].v;if(vis[v])continue;rem[0]=0; dis[v]=E[i].dis;getdis(v,u);//处理u的每个子树的disfor(int j=rem[0];j;--j)//遍历当前子树的disfor(int k=1;k<=m;++k)//遍历每个询问{if(query[k]>=rem[j])test[k]|=judge[query[k]-rem[j]];//如果query[k]-rem[j]的路径存在就标记第k个询问}for(int j=rem[0];j;--j)//保存出现过的dis于judge{q[++p]=rem[j];judge[rem[j]]=1;}}for(int i=1;i<=p;++i)//处理完这个子树就清空judgejudge[q[i]]=0;//特别注意一定不要用memeset,会T}

solve则是对每一个根进行处理,通过solve来调用上述函数,在递归过程中不断重复一样的过程

void solve(int u)
{   //judge[i]表示到根距离为i的路径是否存在vis[u]=judge[0]=1;calc(u);//处理以u为根的子树for(int i=head[u];i;i=E[i].nxt)//对每个子树进行分治{int v=E[i].v;if(vis[v])continue;sum=size[v]; maxp[rt=0]=inf;//注意sum是以v为根的子树大小getrt(v,0);solve(rt);//在子树中找重心并递归处理}
}

代码:

//niiick
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;int read()
{int f=1,x=0;char ss=getchar();while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}return f*x;
}const int inf=10000000;
const int maxn=100010;
int n,m;
struct node{int v,dis,nxt;}E[maxn<<1];
int tot,head[maxn];
int maxp[maxn],size[maxn],dis[maxn],rem[maxn];
int vis[maxn],test[inf],judge[inf],q[maxn];
int query[1010];
int sum,rt;
int ans;void add(int u,int v,int dis)
{E[++tot].nxt=head[u];E[tot].v=v;E[tot].dis=dis;head[u]=tot;
}void getrt(int u,int pa)//求重心 
{size[u]=1; maxp[u]=0;for(int i=head[u];i;i=E[i].nxt) {int v=E[i].v;if(v==pa||vis[v]) continue;getrt(v,u);size[u]+=size[v];maxp[u]=max(maxp[u],size[v]);}maxp[u]=max(maxp[u],sum-size[u]);if(maxp[u]<maxp[rt]) rt=u;
}void getdis(int u,int fa)//每一个子节点到根的距离 
{rem[++rem[0]]=dis[u];for(int i=head[u];i;i=E[i].nxt){int v=E[i].v;if(v==fa||vis[v])continue;dis[v]=dis[u]+E[i].dis;getdis(v,u);}
}void calc(int u)
{int p=0;for(int i=head[u];i;i=E[i].nxt){int v=E[i].v;if(vis[v])continue;rem[0]=0; dis[v]=E[i].dis;getdis(v,u);//处理u的每个子树的disfor(int j=rem[0];j;--j)//遍历当前子树的disfor(int k=1;k<=m;++k)//遍历每个询问{if(query[k]>=rem[j])test[k]|=judge[query[k]-rem[j]];//如果query[k]-rem[j]的路径存在就标记第k个询问}for(int j=rem[0];j;--j)//保存出现过的dis于judge{q[++p]=rem[j];judge[rem[j]]=1;}}for(int i=1;i<=p;++i)//处理完这个子树就清空judgejudge[q[i]]=0;//特别注意一定不要用memeset,会T}void solve(int u)
{   //judge[i]表示到根距离为i的路径是否存在vis[u]=judge[0]=1; calc(u);//处理以u为根的子树for(int i=head[u];i;i=E[i].nxt)//对每个子树进行分治{int v=E[i].v;if(vis[v])continue;sum=size[v]; maxp[rt=0]=inf;//注意sum是以v为根的子树大小getrt(v,0); solve(rt);//在子树中找重心并递归处理}
}int main()
{n=read();m=read();for(int i=1;i<n;++i){int u=read(),v=read(),dis=read();add(u,v,dis);add(v,u,dis);}for(int i=1;i<=m;++i)query[i]=read();//先记录每个询问以离线处理maxp[rt]=sum=n;//第一次先找整棵树的重心getrt(1,0); solve(rt);//对树进行点分治for(int i=1;i<=m;++i){if(test[i]) printf("AYE\n");else printf("NAY\n");}return 0;
}

代码2

//#pragma optimize("Ofast")
#include<bits/stdc++.h>
#define MAXN 10005
#define MAXK 10000007
#define inf int(16843009)
using namespace std;
typedef long long ll;int N,M,K[MAXN];
struct edge{int v,w;edge(int v=0, int w=0):v(v), w(w){}
};vector<edge> adj[MAXN];int vis[MAXN],d[MAXN],sz[MAXN];
int rt,cnt;void dfs_rt(int u, int fa, int tot){//++cnt;sz[u] = 1;int v,w,n=0;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;if(v==fa || vis[v]) continue;dfs_rt(v,u,tot);sz[u] += sz[v];n = max(n, sz[v]);}n = max(n, tot-sz[u]);if(2*n <= tot) rt = u;
}bool t[MAXK], ans[MAXN]; void dfs1(int u, int fa){++cnt;for(int i=1;i<=M;i++){if(d[u] <= K[i]) ans[i] |= t[K[i] - d[u]];}int v,w;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v; w = adj[u][k].w;if(v==fa || vis[v]) continue;d[v] = d[u] + w;dfs1(v,u);}
}void dfs2(int u, int fa, int flag){for(int i=1;i<=M;i++){if(d[u] <= K[i]){if(flag==1) t[d[u]] = 1;else t[d[u]] = 0;}}int v;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;if(v==fa || vis[v]) continue;dfs2(v,u,flag);}
}void work(int u, int fa, int tot){dfs_rt(u,fa,tot);u = rt;vis[u] = 1; d[u] = 0;t[0] = 1;int v,w;for(int k=0;k<adj[u].size();k++){v = adj[u][k].v; w = adj[u][k].w;if(vis[v]) continue;cnt = 0;d[v] = w;dfs1(v,u);sz[v] = cnt;dfs2(v,u,+1);}dfs2(u,0,-1);for(int k=0;k<adj[u].size();k++){v = adj[u][k].v;if(vis[v]) continue;work(v,u,sz[v]);}
}int main(){scanf("%d%d", &N, &M);int u,v,w;for(int i=1;i<N;i++){scanf("%d%d%d", &u, &v, &w);adj[u].push_back(edge(v,w));adj[v].push_back(edge(u,w));}for(int i=1;i<=M;i++){scanf("%d", &K[i]);}t[0] = 1;work(1,0,N);for(int i=1;i<=M;i++){if(ans[i]) puts("AYE");else puts("NAY");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core中使用GraphQL - 第二章 中间件

前文&#xff1a;ASP.NET Core中使用GraphQL - 第一章 Hello World中间件如果你熟悉ASP.NET Core的中间件&#xff0c;你可能会注意到之前的博客中我们已经使用了一个中间件&#xff0c;这个中间件负责输出了当前查询的结果。中间件的定义&#xff1a;中间件是装载在应用程序管…

【模板】AC自动机

ACM模板 目录插入以及构建AC自动机【模板】AC自动机&#xff08;二次加强版&#xff09;ac自动机fail树上dfs序建可持久化线段树插入以及构建AC自动机 #include<queue> #include<string> const int N200010; struct node {int chd[26],fail,cnt; }tree[N]; void i…

ASP.NET Core中Ocelot的使用:基于服务发现的负载均衡

本系列相关文章&#xff1a;《ASP.NET Core中Ocelot的使用&#xff1a;API网关的应用》《ASP.NET Core中Ocelot的使用&#xff1a;基于Spring Clound Netflix Eureka的动态路由》本文将基于前两篇文章所述内容&#xff0c;继续介绍如何在服务发现和动态路由的基础上&#xff0c…

CF643F-Bears and Juice【组合数学】

正题 题目链接:https://www.luogu.com.cn/problem/CF643F 题目大意 题目有点奇怪就直接放翻译了 有 nnn 只熊和若干桶果汁和恰好一桶酒&#xff0c;每一天每只熊会选择一些桶&#xff08;可能不选&#xff09;并各喝一 杯&#xff0c;喝到酒的熊会去睡觉并不再回来&#xff…

【模板】Manacher算法

ACM模板 目录初始化以及构造初始化以及构造 数组下标从1开始即cin>>s1 由于奇回文串和偶回文串某些性质不同&#xff0c;我们首先通过init()操作使得新串中所有回文串的长度都变成奇数&#xff0c;返回值是新串的长度&#xff08;原串中的下标i对应新串中的2i&#xff09…

POJ2155 - Matrix(二维树状数组)

POJ2155 - Matrix 文章目录题目题解&#xff1a;代码题目 给你一个二维矩阵&#xff0c;初始化为0&#xff0c;然后可以进行两次操作&#xff1a; C:x,y,x1,y2 对该小矩阵内的数进行取反 Q:查询某个点是0还是1 题解&#xff1a; C是区间修改&#xff0c;Q是单点查询&#xf…

牛客挑战赛48C-铬合金之声【Prufer序列】

正题 题目链接:https://ac.nowcoder.com/acm/contest/11161/C 题目大意 nnn个点加mmm条边使得不存在环&#xff0c;每种方案的权值是所有联通块的大小乘积。 求所有方案的权值和。 1≤n≤109,1≤m≤1071\leq n\leq 10^9,1\leq m\leq 10^71≤n≤109,1≤m≤107 解题思路 就是分…

F - Sugoroku2(期望dp)

F - Sugoroku2 期望dp&#xff1a;fuf_ufu​表示到达终点的期望于是有 fu{0,u≥nf0,u∈Afu1⋯fumm1f_u\begin{cases} 0,u\ge n \\f_0,u\in A\\ \frac{f_{u1}\dotsf_{um}}{m}1 \end{cases}fu​⎩⎪⎨⎪⎧​0,u≥nf0​,u∈Amfu1​⋯fum​​1​ 由于存在返回f0f_0f0​的操作&…

.NET Core2使用Azure云上的Iot-Hub服务

基于工业4.0大背景下的工业物联网是近几年内热门的话题&#xff0c;依靠信息化技术企业可以实现数字化转型&#xff0c;生产可以实现智能化制造&#xff0c;设备可以实现自动化运作。然而&#xff0c;海量的数据采集是整个建设过程的基础环节&#xff0c;如何处理与利用这海量的…

Matrix Subtraction(小米icpc邀请赛第一场)

Matrix Subtraction 题意&#xff1a; 一个给定的矩阵&#xff0c;然后给定一个子矩阵的大小&#xff0c;子矩阵可以 将覆盖矩阵的区域的值减1&#xff0c;问能否将矩阵全部减为0 题解&#xff1a; 思路和下面这个链接讲的题十分相似 传送 本质就是二维树状数组差分求解 用…

E - Rotate and Flip(线性代数矩阵坐标变换)

E - Rotate and Flip 顺时针 [010−100001][xy1][y−x1]\begin{bmatrix} 0 & 1 & 0\\ -1&0&0\\0 &0&1 \end{bmatrix}\begin{bmatrix} x\\y\\1 \end{bmatrix}\begin{bmatrix} y\\-x\\1 \end{bmatrix}⎣⎡​0−10​100​001​⎦⎤​⎣⎡​xy1​⎦⎤​⎣…

CF755G-PolandBall and Many Other Balls【倍增FFT】

正题 题目链接:https://www.luogu.com.cn/problem/CF755G 题目大意 nnn个东西排成一排&#xff0c;每个组可以选择一个单独的物品或者两个连续的物品&#xff0c;一个物品不同同时在两个组里&#xff0c;但是可以不在组里。对于i∈[1,k]i\in[1,k]i∈[1,k]求分成iii组的方案数。…

Intelligent Warehouse(小米邀请赛)

题目 题意&#xff1a; n个数字&#xff0c;问存在的最长的一组数&#xff0c;使得其中任意两个数的都是倍数关系&#xff0c;问最长的长度是多少 题解&#xff1a; 暴力。。。 没想到暴力就能做&#xff0c;当时就该交上去试试的 用dp[i]表示当期选的所有数都是i的约数且符…

SmartCode.ETL 这不是先有鸡还是蛋的问题!

继国庆节 SmartCode 正式版&#xff08;SmartCode.Generator&#xff09;发布之后&#xff0c;SmartCode 迎来了新的能力 SmartCode.ETL !SmartCode 正式版从开始发布就从未说过自己仅仅是个代码生成器&#xff0c;这点上从我第一次宣布SmartCode正式开源的文章就可以说明&…

codeforces1469 E. A Bit Similar

E. A Bit Similar 代码抄的这份题解 找到一个长度为k的串使得在s长度为k的子串中&#xff0c;对于所有子串答案串都至少有一位相同。也就是如果将s长度为k的子串全部按位取反&#xff0c;那么答案串不能与这些反串匹配。 现在问题转化成&#xff0c;找到一个答案串&#xff…

对拍

参考博客 晚上不想刷题。。无聊的开始研究对拍 以前oi的时候看过对拍&#xff0c;奈何当时水平太差根本用不上对拍&#xff0c;&#xff08;现在水平也不咋地。。&#xff09; 上面那个博文讲的非常好。。 对拍最终的就是 对拍程序.bat 首先第一步&#xff1a;生成一组输入数据…

P7444-「EZEC-7」猜排列【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P7444 题目大意 一个长度为nnn的排列&#xff0c;已知每个cic_ici​表示那个排列中mexmexmex为iii的区间个数。求满足条件的排列个数 1≤n≤5105,ci≥0,∑i1ncin(n1)2−11\leq n\leq 5\times 10^5,c_i\geq 0,\sum_{i1}^nc_i\…

dubbo线程池为什么耗尽

文章概述 大家可能都遇到过DUBBO线程池打满这个问题&#xff0c;报错如下&#xff0c;本文我们就一起分析DUBBO线程池打满这个问题。 cause: org.apache.dubbo.remoting.RemotingException: Server side(10.0.0.100,20881) thread pool is exhausted, detail msg:Thread pool …

手把手教你写DI_0_DI是什么?

DI是什么&#xff1f;Dependency Injection 常常简称为&#xff1a;DI。它是实现控制反转&#xff08;Inversion of Control – IoC&#xff09;的一个模式。fowler 大大大神 “几十年”前的经典文章 https://www.martinfowler.com/articles/injection.html 说的很清楚。“几十…

C++顺序创建txt文件

今天下午在对拍数据的时候感觉好麻烦。。 一次次手调文件名称&#xff0c;突然想起可以直接写段程序集中操作 顺序输出 #include <iostream> #include <fstream> #include<string> using namespace std;int main () {ofstream File;for(int i0;i<3;i){str…