poj2114 Boatherds
来源:互联网 发布:杭州淘宝大学培训机构 编辑:程序博客网 时间:2024/06/12 04:53
判断树上是否存在长度为k的路径
关键词:点分治、等值特判、扫描法
判断方法仍为扫描法,只不过相等的时候需要特判,否则会错过许多条k长路径
#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>#define maxn 20010#define lowbit(x) x&(-x)#define mem(a,b) memset(a,b,sizeof(a))#define ll long long#define INF 0x3f3f3f3fusing namespace std;int n,m;int k;struct Edge{ int to,next; ll w;}edge[maxn*2];int head[maxn],tot;ll sum,f[maxn],vis[maxn],son[maxn],core,d[maxn];//getcorell ans,deep[maxn];void init(){ mem(head,-1),tot=0;}void add(int a,int b,ll c){ edge[tot].to=b,edge[tot].next=head[a],edge[tot].w=c; head[a]=tot++;}void getcore(int u,int fa){ son[u]=1,f[u]=0;//每次更新前必须初始化!!!---dfs可以在搜索子树前在内部对点初始化 for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa||vis[v]) continue;//除去已找到的重心后求子树重心 getcore(v,u); son[u]+=son[v],f[u]=max(f[u],son[v]); } f[u]=max(f[u],sum-son[u]); if(f[u]<f[core]) core=u;//core记录该树重心}void getdeep(int u,int fa){//得到u子树每个节点的深度 deep[++deep[0]]=d[u]; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; ll w=edge[i].w; if(v==fa||vis[v]) continue; d[v]=d[u]+w; getdeep(v,u); }}ll cal(int u,int w){//1.该点是重心:求该点子树每点到该点深度2.该点父节点是重心:求该点子树到父节点的深度 deep[0]=0,d[u]=w; getdeep(u,0); sort(deep+1,deep+deep[0]+1); int tmp=0; for(int l=1,r=deep[0];l<r;){ if(deep[l]+deep[r]<k) l++; else if(deep[l]+deep[r]>k) r--; else{//计数出错!!!---可能出现相同的数,此时应该特殊处理!!! if(deep[l]==deep[r]){ tmp+=((r-l)*(r-l+1)/2); break; } int st=l,en=r; while(deep[st]==deep[l]) st++; while(deep[en]==deep[r]) en--; tmp+=(st-l)*(r-en); l=st,r=en; } } return tmp;}void work(int u){ ans+=cal(u,0);//经过原树重心的k路径条数 vis[u]=1;//原树重心已算,标记 for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to,w=edge[i].w; if(vis[v]) continue;//如果v已经作为重心枚举过,u不会遍历到v,因此不必除去 ans-=cal(v,w);//除去经过重心同一子树的路径 sum=son[v];//更改当前树节点总和 core=0; getcore(v,core); work(core); }}int main(){ //freopen("a.txt","r",stdin); while(scanf("%d",&n)!=EOF){ if(!n) break; init(); for(int i=1;i<=n;i++){ int a; ll b; while(scanf("%d",&a)){ if(!a) break; scanf("%lld",&b); add(a,i,b),add(i,a,b); } } while(scanf("%d",&k)){ if(!k) break; mem(vis,0),ans=0; core=0,sum=n,f[0]=INF; getcore(1,0); work(core); if(ans) printf("AYE\n"); else printf("NAY\n"); } printf(".\n"); } return 0;}bug:等值特判
0 0
- poj2114 Boatherds
- poj2114 Boatherds
- POJ2114-Boatherds
- poj2114 Boatherds
- 【POJ2114】Boatherds 树分治
- POJ2114 Boatherds 点分治
- [POJ2114]Boatherds(点分治+二分)
- [树的点分治] [POJ2114] Boatherds
- poj2114 Boatherds(好久没翻译的说)
- POJ2114【树分治】
- POJ2114(树分治)
- poj 2114 Boatherds
- POJ 2114 Boatherds
- POJ 2114Boatherds
- poj 2114 Boatherds
- POJ 2114 Boatherds
- poj2114(树的点分治)
- poj 2114 Boatherds 点分治
- 深入理解Android卷一中下载Android源代码详述
- win7下通过easyBCD引导安装Ubuntu14.04
- iOS 逆向之ARM汇编
- 在 Ubuntu 14.04 Server 上安装 Ganglia
- Ubuntu 14.04 LTS Server 安装 LAMP Server
- poj2114 Boatherds
- 追忆研发的日子
- iOS 开发之Widget的开发及使用(上)
- vector 释放内存 swap
- Jquery<3>操作DOM
- iOS 开发之Widget的开发及使用(下)
- Spring Scope
- 水题HDU 2138 How many prime numbers
- Andriod Dialog 加载框 自定义,公用