点分治:统计长度为K的路径条数
来源:互联网 发布:淘宝鲁班系统 编辑:程序博客网 时间:2024/04/26 20:31
套用第一种点分治模板——先加后减法。
计算过程略微不同,得到deep数组后,计算和为K的路径对数
1.剔除d[i]+d[i]==K的情况
2.遍历一遍后,每种情况计算了两次,最后需要除2
#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<limits.h>#include<queue>#include<vector>#define ll long long#define MP make_pair#define MP(x,y) make_pair((x),(y))#define X first#define Y second#define oo 0x3f3f3f3fconst ll INF = 0x0fffffffffffffff;using namespace std;typedef long long lld;const int maxn = 10000+10;int n,K;typedef pair<int,int> F;vector<F> e[maxn];int s[maxn],deep[maxn],d[maxn],ans;bool vis[maxn];void add(int u,int v,int w) { e[u].push_back(MP(w,v)); }F getcore(int u,int f,int sum){ s[u]=1; int lar=0; F ans=MP(oo,0); for(int i=0;i<e[u].size();i++){ int v=e[u][i].Y; if(v==f||vis[v]) continue; F x=getcore(v,u,sum); s[u]+=s[v]; lar=max(lar,s[v]);//记录子树节点的最大值 ans=min(ans,x);//记录子树结果的最小值(权值最小,然后编号最小) } lar=max(lar,sum-s[u]); ans=min(ans,MP(lar,u)); return ans;}void build(){ for(int i=1;i<=n;i++) e[i].clear(); for(int i=1;i<=n;i++){ int v,w; while(scanf("%d",&v)!=EOF&&v){ scanf("%d",&w); add(i,v,w),add(v,i,w); } }}void getdeep(int u,int f){ deep[++deep[0]]=d[u]; for(int i=0;i<e[u].size();i++){ int v=e[u][i].Y,w=e[u][i].X; if(v==f||vis[v]) continue; d[v]=d[u]+w; getdeep(v,u); }}int cal(int u,int w){//统计初始长度为w,长度和不大于K的路径个数(可重合) d[u]=w,deep[0]=0,getdeep(u,-1);//得到以u为根节点,u的初始深度为w,其他点的深度 sort(deep+1,deep+deep[0]+1); int tmp=0; for(int i=1;i<=deep[0];i++){ int r=upper_bound(deep+1,deep+deep[0]+1,K-deep[i])-deep; int l=lower_bound(deep+1,deep+deep[0]+1,K-deep[i])-deep; tmp+=(r-l); if(i>=l&&i<r) tmp--; } return tmp/2;}void work(int u,int f,int sum){ u=getcore(u,f,sum).Y; ans+=cal(u,0); vis[u]=1; for(int i=0;i<e[u].size();i++){ int v=e[u][i].Y,c=e[u][i].X; if(vis[v]||v==f) continue; ans-=cal(v,c); work(v,u,s[v]); }}int main(){ // freopen("a.txt","r",stdin); while(scanf("%d",&n)!=EOF&&n){ build(); scanf("%d",&K); while(K){ memset(vis,0,sizeof(vis)),ans=0; work(1,-1,n); if(ans) printf("AYE\n"); else printf("NAY\n"); scanf("%d",&K); } printf(".\n"); }}
0 0
- 点分治:统计长度为K的路径条数
- 点分治:统计长度不大于K的路径条数
- 【codechef】 Prime Distance On Tree【求树上路经长度为i的路径条数】【点分治+FFT】
- poj 2114 树分治(是否存在长度恰为k的路径)
- 树形DP 统计树中长度为K的路径数量 CodeForces 161D Distance in Tree
- 树形DP 统计树中长度为K的路径数量 CodeForces 161D Distance in Tree
- 树链剖分-点的分治(链的点的个数为k的点对数)
- CF 161D Distance in Tree 树形DP(套路,路径长度为k点对)
- 树链剖分-点的分治(点数为k且距离最长的点对)
- 【树的分治统计点对距离<=k】POJ 1741
- 树上路径统计——点分治の板子
- 分治-寻找第k小的数
- [线段树练习5] 线段的条数 - 统计点重复标记数
- 【BZOJ3697】采药人的路径【点分治】
- 【bzoj3697】【采药人的路径】【点分治】
- 【bzoj3697】采药人的路径 点分治
- bzoj3697 采药人的路径 点分治
- [bzoj3784][点分治]树上的路径
- 当大叔爱上小丫头
- 工作日志 4.24
- iOS相册图片缓存(document)以及图片文件流上传服务器功能
- 各向异性扩散PM模型原理与C++实现
- 通州开通3条定向短程公交方便百姓出行
- 点分治:统计长度为K的路径条数
- Android+SSH开发商城App(1)数据库的创建和环境的搭建
- POJ1067 取石子游戏 威佐夫博弈
- 如何实现 基本数据类型 与 基本数据封装类 之间的相互转换
- 开源License对比分析
- tar 打包文件--- 不包含文件所在路径的方法
- GCD
- 一个SQL 查询的性能问题
- python的argparse模块的使用