还是利用点的分治的办法来做,统计的办法不一样了,我的做法是排序并且标记每个点属于哪颗子树。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e4+9;
int head[maxn],lon,n,mm,m;
struct
{
int next,to,w;
}e[maxn<<1];
void edgeini()
{
memset(head,-1,sizeof(head));
lon=0;
}
void edgemake(int from,int to,int w)
{
e[++lon].to=to;
e[lon].w=w;
e[lon].next=head[from];
head[from]=lon;
} int son[maxn],maxson[maxn];
bool use[maxn];
int dp(int t,int from)
{
int ans,tmp,now=1e4+9;
son[t]=maxson[t]=0;
for(int k=head[t];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(u==from||use[u]) continue;
tmp=dp(u,t);
if(maxson[tmp]<now)
{
now=maxson[tmp];
ans=tmp;
}
son[t]+=son[u];
maxson[t]=max(son[u],maxson[t]);
}
son[t]++;
maxson[t]=max(maxson[t],mm-son[t]);
if(maxson[t]<now) ans=t;
return ans;
}
int d[maxn],top;
struct D
{
int data,ss;
bool operator <(const D & xx) const
{
return data<xx.data;
}
}a[maxn];
void dfs(int t,int from)
{
a[++top].data=d[t];
son[t]=0;
for(int k=head[t];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(u==from||use[u]) continue;
d[u]=d[t]+e[k].w;
dfs(u,t);
son[t]+=son[u];
}
son[t]++;
} int ss[maxn];
int cal(int l,int r)
{
int ret=0;
for(;l<r;)
{
while(r>l&&a[l].data+a[r].data>m) r--;
while(r>l&&a[l].data+a[r].data<m) l++;
if(a[l].data+a[r].data==m)
{
int ll=a[l].ss,rr=a[r].ss;
if(ll!=rr) return true;
while(l<r&&a[l+1].data==a[l].data)
{
if(a[l+1].ss!=ll) return true;
l++;
}
while(l<r&&a[r-1].data==a[r].data)
{
if(a[r-1].ss!=rr) return true;
r--;
}
l++;
r--;
}
}
return false;
} bool solve(int t)
{
int now=dp(t,0);
use[now]=1;
d[now]=top=0;
dfs(now,0);
int tmp=2,con=0;
for(int k=head[now];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(use[u]) continue;
con++;
for(int i=tmp;i<tmp+son[u];i++)
a[i].ss=con;
tmp+=son[u];
}
sort(a+1,a+tmp);
a[1].ss=0;
int ret=cal(1,tmp-1);
if(ret) return true;
for(int k=head[now];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(use[u]) continue;
mm=son[u];
if(solve(u)) return true;
}
return false;
} int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d", &n)!=EOF&& n)
{
edgeini();
for(int i=1,to,w;i<=n;i++)
{
while(scanf("%d",&to),to)
{
scanf("%d",&w);
edgemake(i,to,w);
edgemake(to,i,w);
}
}
int tmp;
while(scanf("%d",&tmp)!=EOF&&tmp)
{
m=tmp;
mm=n;
memset(use,0,sizeof(use));
if(solve(1))
printf("AYE\n");
else
printf("NAY\n");
}
printf(".\n");
}
return 0;
}

poj 2114 Boatherds 树的分治的更多相关文章

  1. POJ 2114 Boatherds 树分治

    Boatherds     Description Boatherds Inc. is a sailing company operating in the country of Trabantust ...

  2. POJ 1741 Tree 树的分治

    原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...

  3. poj 2114 Boatherds (树分治)

    链接:http://poj.org/problem?id=2114 题意: 求树上距离为k的点对数量: 思路: 点分治.. 实现代码: #include<iostream> #includ ...

  4. POJ 2114 Boatherds【Tree,点分治】

    求一棵树上是否存在路径长度为K的点对. POJ 1714求得是路径权值<=K的路径条数,这题只需要更改一下统计路径条数的函数即可,如果最终的路径条数大于零,则说明存在这样的路径. 刚开始我以为只 ...

  5. Poj 2114 Boatherds(点分治)

    Boatherds Time Limit: 2000MS Memory Limit: 65536K Description Boatherds Inc. is a sailing company op ...

  6. POJ 2114 Boatherds 划分树

    标题效果:鉴于一棵树,问有两点之间没有距离是k的. 数据的多组 思维:和IOI2011的Race喜欢.不是这么简单.阅读恶心,我是在主要功能的别人的在线副本. CODE: #include <c ...

  7. POJ 2114 - Boatherds

    原题地址:http://poj.org/problem?id=2114 题目大意: 给定一棵点数为\(n~(n \le 10000)\)的无根树,路径上有权值,给出m组询问($m \le 100$), ...

  8. POJ 1741 Tree 树的分治(点分治)

    题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...

  9. poj 1741 Tree (树的分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30928   Accepted: 10351 Descriptio ...

随机推荐

  1. 试用阿里云RDS的MySQL压缩存储引擎TokuDB

    以前就用过自己搭建MySQL服务器的两种存储引擎MyISAM和InnoDB(也用过一点Memory方式),在今年初转向阿里云关系型数据库服务RDS的时候,看到可调参数中有一个TokuDB,不过不太了解 ...

  2. ALV的html表头

    在ALV的function的exporting里添加属性: I_CALLBACK_HTML_TOP_OF_PAGE = alv_top_of_page 定义form响应上述ALV属性 *&-- ...

  3. 您应该了解的 Windows Azure 网站在线工具

     编辑人员注释:本文章由Windows Azure 网站团队的软件开发者 Amit Apple 撰写. 如果想要了解并亲身参与计算资源管理,那么您一定会很高兴得知这一消息:Windows Azur ...

  4. Windows Azure HDInsight 支持预览版 Hadoop 2.2 群集

     Windows Azure HDInsight 支持预览版 Hadoop 2.2 群集 继去年 10 月推出 Windows Azure HDInsight 之后,我们宣布 Windows Az ...

  5. HDU 1851 A Simple Game

    典型的尼姆博弈,在n对石子中,告诉你每堆的数目和每次从该堆最多可以取的数目,求最终谁将其取完. 题解:SG(i)=mi%(li+1),求异或值即可. #include <cstdio> i ...

  6. PHP第一章学习——了解PHP(下)

    继续昨天的部分! —————————————————————————————— 首先Ubuntu下安装Apache软件: ubuntu更新源有问题,又要解决半天! 我现在很冷静! 安装Apache教程 ...

  7. 10003 Cutting Sticks(区间dp)

      Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog ...

  8. PHP中用到的一些字符串函数

    /*常用的字符串输出函数   *   * echo()   输出字符串   * print()  输出一个或多个字符串   * die()  输出一条信息,并退出当前脚本   * printf()  ...

  9. 讲讲金融业务(一)--自助结算终端POS

    之前在群里和大家聊天的时候,发现好多人对银行业务比較感兴趣,或许是由于大家对银行不了解,以为非常神奇的样子.全部,从这周開始我打算把我肚子里的墨水慢慢地倒出来,和大家分享分享.   在技术还不发达的时 ...

  10. poj 3128 Leonardo&#39;s Notebook(置换的幂)

    http://poj.org/problem?id=3128 大致题意:输入一串含26个大写字母的字符串,能够把它看做一个置换.推断这个置换是否是某个置换的平方. 思路:具体解释可參考url=ihxG ...