poj2114

Boatherds
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 1195   Accepted: 387

Description

Boatherds Inc. is a sailing company operating in the country of Trabantustan and offering boat trips on Trabantian rivers. All the rivers originate somewhere in the mountains and on their way down to the lowlands they gradually join and finally the single resulting
river flows to the sea. Moreover, the Trabantian villages are exactly at the rivers' springs, junctions and at the mouth of the largest river. Please note that more than 2 rivers can join at a junction. However, the rivers always form a tree (with villages
as vertices). 



The pricing policy of the Boatherds is very simple: each segment of each river between two villages is assigned a price (the price is same in both directions), so if a tourist requests a journey between any two villages, the ticket office clerks just add the
prices of the segments along the only path between the villages. 



One day, a very strange tourist appeared. She told the clerks that she returns to her country on the next day and she wants to spend all the remaining money on a boat trip, so they should find a route with exactly this cost. Being just poor (ahem) businessmen,
they have asked the Abacus Calculator Makers for help. 



You are given a description of the river network with costs of river segments and a sequence of integers x1,..., xk. For each xi, you should determine if there is a pair of cities (a, b) in the river network such that the cost of the trip between a and b is
exactly xi. 

Input

The input consists of several instances. Each instance is described by (in the following order):

  • A single line containing a single integer: the number of villages N (1 <= N <= 10 000).
  • N lines describing the villages. The i-th of these lines (1 <= i <= N) describes the village with number i. It contains space separated integers d1, c1, d2, c2, , dki, cki, 0. The dj's are numbers of villages from which the rivers
    flow directly to the village i (with no other villages in between), each cj is the price of the journey between villages i and dj. Moreover, 2 <= dj <= N and 0 <= cj <= 1 000. Village 1 always corresponds to the mouth of the largest river, therefore no di
    can ever be equal to 1.
  • M <= 100 lines describing the queries. The i-th of these lines corresponds to the i-th query and contains a single integer xi (1 <= xi <= 10 000 000).
  • The instance is finished by a single line containing the number 0.

The whole input is ended by a single line containing the number 0. 

Output

For each instance you should produce a sequence of M lines (where M is the number of queries in the particular instance). The i-th of these lines contains the word "AYE" if there exists a pair of cities in the river network which is connected by a path of cost
xi, or the word "NAY" otherwise. 



Output for each instance must be followed by a single line containing just the dot character. 

Sample Input

6
2 5 3 7 4 1 0
0
5 2 6 3 0
0
0
0
1
8
13
14
0
0

Sample Output

AYE
AYE
NAY
AYE
.

题目大意:

求一棵树上是否存在路径长度为K的点对。

POJ 1714求得是路径权值<=K的路径条数,这题只需要更改一下统计路径条数的函数即可,如果最终的路径条数大于零,则说明存在这样的路径。

刚开始我以为只要在分治过程中出现过长度为K的就算是找到了,其实不然,因为可能是相同子树里面的两个结点,这个结果显然是错误的。

修改内容:例如一个序列0,1,2,2,3,3,3,4,4,4,6,8,9

设k=6对于该子树,先找到0,1,2,2,3,3,3,4,4,4,6,sum+=1*1,

然后:搜到2,2,3,3,3,4,4,4,sum+=2*3(2个2与3个4)

最后搜到3,3,3,sum+=3*2/2;

return sum=9;

程序:

#include"string.h"
#include"stdio.h"
#include"stdlib.h"
#include"queue"
#include"stack"
#include"iostream"
#include"algorithm"
#include"vector"
#define inf 1000000000
#define M 51111
using namespace std;
struct node
{
int u,v,w,next;
}edge[M*3];
int t,head[M],use[M],dis[M],son[M],limit[M],k,cnt,MN,ID,ans;
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
edge[t].u=u;
edge[t].v=v;
edge[t].w=w;
edge[t].next=head[u];
head[u]=t++;
}
void dfs_size(int u,int f)
{
son[u]=1;
limit[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(f!=v&&!use[v])
{
dfs_size(v,u);
son[u]+=son[v];
limit[u]=max(limit[u],son[v]);
}
}
}
void dfs_root(int root,int u,int f)
{
if(son[root]-son[u]>limit[u])
limit[u]=son[root]-son[u];
if(MN>limit[u])
{
ID=u;
MN=limit[u];
}
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(f!=v&&!use[v])
dfs_root(root,v,u);
}
}
void dfs_dis(int u,int f,int id)
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(f!=v&&!use[v])
{
dfs_dis(v,u,id+edge[i].w);
}
}
dis[cnt++]=id;
}
int cal(int u,int f,int id)
{
cnt=0;
int sum=0,i,j;
dfs_dis(u,f,id);
sort(dis,dis+cnt);
i=0;
j=cnt-1;
while(i<j)//需要特殊注意的地方
{
if(dis[i]+dis[j]<k)
i++;
else if(dis[i]+dis[j]>k)
j--;
else
{
if(dis[i]==dis[j])
{
sum+=(j-i+1)*(j-i)/2;
break;
}
int st=i,ed=j;
while(dis[st]==dis[i])st++;
while(dis[ed]==dis[j])ed--;
sum+=(st-i)*(j-ed);
i=st,j=ed;
}
}
return sum;
}
void dfs_ans(int root,int u,int f)
{
dfs_size(root,f);
MN=inf;
dfs_root(root,root,f);
ans+=cal(ID,ID,0);
use[ID]=1;
for(int i=head[ID];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!use[v])
{
ans-=cal(v,v,edge[i].w);
dfs_ans(v,v,v);
}
}
}
void slove()
{
ans=0;
memset(use,0,sizeof(use));
dfs_ans(1,1,1);
//printf("%d\n",ans);
if(ans>0)
printf("AYE\n");
else
printf("NAY\n");
}
int main()
{
int n,i,j,w;
while(scanf("%d",&n),n)
{
init();
for(i=1;i<=n;i++)
{
while(scanf("%d",&j),j)
{
scanf("%d",&w);
add(i,j,w);
add(j,i,w);
}
}
while(scanf("%d",&k),k)
{
slove();
}
printf(".\n");
}
return 0;
}

树链剖分-点的分治(dis[i]+dis[j]==k的点对数量)的更多相关文章

  1. 树链剖分-点的分治(点数为k且距离最长的点对)

    hdu4871 Shortest-path tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 130712/130712 K ( ...

  2. 树链剖分-点的分治(链的点的个数为k的点对数)

    hdu4760 Cube number on a tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 ...

  3. [2016北京集训试题7]thr-[树形dp+树链剖分+启发式合并]

    Description Solution 神仙操作orz. 首先看数据范围,显然不可能是O(n2)的.(即绝对不是枚举那么简单的),我们考虑dp. 定义f(x,k)为以x为根的子树中与x距离为k的节点 ...

  4. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  5. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  6. [luogu4886] 快递员(点分治,树链剖分,lca)

    dwq推的火题啊. 这题应该不算是点分治,但是用的点分治的思想. 每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小. 由于这些点一定不能在u的两颗不同的子树里,否则你怎么 ...

  7. 树分治&树链剖分相关题目讨论

    预备知识 树分治,树链剖分   poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...

  8. dsu+树链剖分+树分治

    dsu,对于无修改子树信息查询,并且操作支持undo的问题 暴力dfs,对于每个节点,对所有轻儿子dfs下去,然后再消除轻儿子的影响 dfs重儿子,然后dfs暴力恢复轻儿子们的影响,再把当前节点影响算 ...

  9. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

随机推荐

  1. 'cl.exe' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    1.首先找到vcvars32.bat文件,一般在C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin文件夹下 2.打开cmd黑窗 ...

  2. 总结一发linux常用命令

    显示目录和文件的命令 Ls:用于查看所有文件夹的命令. Dir:用于显示指定文件夹和目录的命令   Tree: 以树状图列出目录内容 Du:显示目录或文件大小 修改目录,文件权限和属主及数组命令 Ch ...

  3. 如何退出Activity?如何安全退出已调用多个Activity的Application?

    对于单一Activity的应用来说,退出很简单,直接finish()即可. 1.抛异常强制退出: 该方法通过抛异常,使程序ForceClose. 验证可以,但是,需要解决的问题是,如何使程序结束掉,而 ...

  4. BCM_GPIO驱动测试

    在写内核驱动的时候,最好先在uboot上,进行裸板测试,验证寄存器,再移植到内核中,这样可以熟悉寄存器,也排除内核中的一些干扰. /********************************** ...

  5. ANSI 标准是为了确保 C++ 的便携性

    ANSI 标准ANSI 标准是为了确保 C++ 的便携性 —— 您所编写的代码在 Mac.UNIX.Windows.Alpha 计算机上都能通过编译. 由于 ANSI 标准已稳定使用了很长的时间,所有 ...

  6. python PIL 库处理文件

    通过PIL库提供的API接口可以很方便的处理图像,功能十分强大: 最近有一个替换png背景色的需求,替换背景色的同时又不能够覆盖原来的文字,之前利用perl 的CD 模块一直没能够正确处理,最终用PI ...

  7. CentOS系统资源常用命令

    系统: # uname -a   # 查看内核/操作系统/CPU信息 # cat /etc/issue # cat /etc/redhat-release # 查看操作系统版本 # cat /proc ...

  8. 蔡勒(Zeller)公式

    来源好搜百科:http://baike.haosou.com/doc/1048888-1109421.html 蔡勒(Zeller)公式,是一个计算星期的公式,随便给一个日期,就能用这个公式推算出是星 ...

  9. 【Java面试题】32 ArrayList和Vector的区别

    1. Vector & ArrayList  相同点: 1.ArrayList和Vector都是继承了相同的父类和实现了相同的接口 2.底层都是数组实现的 3.初始默认长度都为10. 不同点: ...

  10. php跨form提交方法

    1.php curl function curlPost($url,$params) { $postData = ''; foreach($params as $k => $v) { $post ...