poj2114 Boatherds

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的路径……对于询问一个一个点分治……反正n才10000m才100输入好蛋疼……第一行n,接下来n行,每两个数ci、di,表示i和ci有长度为di的边,以0结束。接下来输入询问,以0结束。又有多组数据,以0结束
#include<cstdio>
#include<iostream>
#include<cstring>
#define LL long long
#define N 40010
#define mod 10207
using namespace std;
inline LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct edge{int to,next,v;}e[2*N];
struct hashing{int v,next;}hash[2*N];
int he[N],head[N];
int f[N],son[N],s[N],d[N],query[N];
bool vis[N],ok[N];
int n,m,cnt,tot,root,sum,len,ans;
inline void ins(int u,int v,int w)
{
	e[++cnt].to=v;
	e[cnt].v=w;
	e[cnt].next=head[u];
	head[u]=cnt;
}
inline void insert(int u,int v,int w)
{
	ins(u,v,w);
	ins(v,u,w);
}
inline void inh(int u)
{
	int w=u%mod+132;
	hash[++tot].v=u;
	hash[tot].next=he[w];
	he[w]=tot;
}
inline bool fnd(int u)
{
	if (u<0)return 0;
	int w=u%mod+132;
	for (int i=he[w];i;i=hash[i].next)
		if (u==hash[i].v)return 1;
	return 0;
}
inline void getroot(int x,int fa)
{
	son[x]=1;f[x]=0;
	for (int i=head[x];i;i=e[i].next)
		if (fa!=e[i].to&&!vis[e[i].to])
		{
			getroot(e[i].to,x);
			son[x]+=son[e[i].to];
			f[x]=max(f[x],son[e[i].to]);
		}
	f[x]=max(f[x],sum-son[x]);
	if (f[x]<f[root])root=x;
}
inline void dfs(int x,int fa)
{
	s[++len]=d[x];
	for (int i=head[x];i;i=e[i].next)
		if (!vis[e[i].to]&&fa!=e[i].to)
		{
			d[e[i].to]=d[x]+e[i].v;
			dfs(e[i].to,x);
		}
}
inline void solve(int x)
{
	vis[x]=1;tot=0;
	memset(he,0,sizeof(he));inh(0);
	for (int i=head[x];i;i=e[i].next)
		if (!vis[e[i].to])
		{
			len=0;
			d[e[i].to]=e[i].v;
			dfs(e[i].to,0);
			for (int j=1;j<=m;j++)
			{
				if (ok[j])continue;
				for (int k=1;k<=len;k++)
					if (fnd(query[j]-s[k]))
					{
						ok[j]=1;
						break;
					}
			}
			for (int j=1;j<=len;j++)inh(s[j]);
		}
	for (int i=head[x];i;i=e[i].next)
		if (!vis[e[i].to])
		{
			sum=son[e[i].to];
			root=0;
			getroot(e[i].to,0);
			solve(root);
		}
}
inline void work()
{
	memset(head,0,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(ok,0,sizeof(ok));
	cnt=ans=0;
	for(int i=1;i<=n;i++)
	{
		int x=read(),y;
		while (x)
		{
			y=read();
			insert(i,x,y);
			x=read();
		}
	}
	m=0;
	int xx=read();
	while (xx)
	{
		query[++m]=xx;
		xx=read();
	}
	f[0]=n+1;sum=n;root=0;
	getroot(1,0);
	solve(root);
	for (int i=1;i<=m;i++)
		if (ok[i])printf("AYE\n");else printf("NAY\n");
	printf(".\n");
}
int main()
{
	while (~scanf("%d",&n)&&n)work();
}
时间: 2024-10-13 16:03:35

poj2114 Boatherds的相关文章

【点分治】poj1741 Tree / poj2114 Boatherds / poj1987 Distance Statistics

三道题都很类似.给出1741的代码 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define MAXN 10001 typedef pair<int,int> Point; int n,K,ans; int v[MAXN<<1],w[MAXN<<1],first[MAXN],next[MAXN<<1],en; vo

【poj2114】 Boatherds

http://poj.org/problem?id=2114 (题目链接) 题意 给出一棵树,问是否存在两点间的距离为K. Solution 点分治嘛,跟poj1741差不多.. 然而为什么我调了一个下午..map真是坑死了,各种TLE,以后再也不写了. 代码 // poj2114 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cs

【POJ2114】Boatherds 树分治

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44308173"); } 题意: 求是否有长度为K的路径. 每组数据 N,表示树有N个点. 然后N行,每行若干个数对(a,b),其中第i行时表示i到a有一条长为b的无向边.输入到0截止. 然后若干个数表示K,每个数输出下. 到0为止.

POJ 2114 Boatherds

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 f

点分治练习: boatherds

[题面] 求一颗树上距离为K的点对是否存在 输入数据 n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径 接下来m行每行询问一个K 输出数据 对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号) 数据范围 对于30%的数据n<=100 对于60%的数据n<=1000,m<=50 对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000 [思路] 树分治. 离线存储m个询问.分治判断该m个询问

poj2114 寻找树上存在长度为k点对,树上的分治

寻找树上存在长度为k点对,树上的分治  代码和  这个  差不多 ,改一下判断的就好 #include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; const int maxn=10004; int H[maxn],nx[maxn*2],to[maxn*2],numofE,d

POJ 2114 Boatherds (树上点分治)

题目地址:POJ 2114 点分治水题.只是把距离小于等于k改成了等于k.稍微加一点处理就可以了. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #incl

poj1741+poj1987+poj2114——点分治入门题集合

最近看了看点分治,从poj上找到几道题,都比较裸.而且感觉这三道题都长得差不多呀qwq ------------------------------------------------ [poj 1741]Tree 题意:给定一棵边带权的树,求两点之间的距离小于或等于K的点对个数. 找重心,相当于把无根树转变为有根树.再利用分治的思想(根据经过重心或不经过重心来划分). 对于在同一个子树的情况要单独拎出来算并减去它们(因为是不该算在内的呀qwq) 另外选取重心的好处是时间复杂度O(NlogN*l

POJ 2114 Boatherds 树的分治

题目大意:给出一棵树,问有没有两点之间的距离是k的.多组数据 思路:和IOI2011的Race一样,比那个简单.读入太恶心了,我是上网上抄的别人的主函数. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 #define INF 0x3f3f3f3f using namespace std; int poi