【poj2114】 Boatherds

http://poj.org/problem?id=2114 (题目链接)

题意

  给出一棵树,问是否存在两点间的距离为K。

Solution

  点分治嘛,跟poj1741差不多。。

  然而为什么我调了一个下午。。map真是坑死了,各种TLE,以后再也不写了。

代码

// poj2114
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#define LL long long
#define MOD 100000000
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

set<int> s;
const int maxn=10010;
struct edge {int to,next,w;}e[maxn<<1];
int head[maxn],size[maxn],deep[maxn],d[maxn],f[maxn],vis[maxn],ans[maxn],q[maxn];
int m,sum,rt,n,cnt;

void link(int u,int v,int w) {
	e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
	e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void Init() {
	cnt=0;f[0]=inf;
	for (int i=1;i<=n;i++) head[i]=f[i]=vis[i]=0;
}
void calroot(int x,int fa) {
	size[x]=1;f[x]=0;
	for (int i=head[x];i;i=e[i].next)
		if (!vis[e[i].to] && e[i].to!=fa) {
			calroot(e[i].to,x);
			size[x]+=size[e[i].to];
			f[x]=max(f[x],size[e[i].to]);
		}
	f[x]=max(f[x],sum-size[x]);
	if (f[x]<f[rt]) rt=x;
}
void caldeep(int x,int fa) {
	deep[++deep[0]]=d[x];
	for (int i=head[x];i;i=e[i].next)
		if (!vis[e[i].to] && e[i].to!=fa) {
			d[e[i].to]=d[x]+e[i].w;
			caldeep(e[i].to,x);
		}
}
void cal(int x,int now) {
	d[x]=now;deep[0]=0;
	caldeep(x,0);
	for (int i=1;i<=m;i++) if (!ans[i]) {
			for (int j=1;j<=deep[0];j++) if (q[i]>=deep[j]) {
					if (q[i]-deep[j]==0) ans[i]=1;
					else if (s.count(q[i]-deep[j])) ans[i]=1;
				}
		}
	for (int i=1;i<=deep[0];i++) s.insert(deep[i]);
}
void solve(int x) {
	vis[x]=1;s.clear();
	for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) cal(e[i].to,e[i].w);
	for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
		sum=size[e[i].to];
		rt=0;calroot(e[i].to,x);
		solve(rt);
	}
}
int main() {
	while (scanf("%d",&n)!=EOF && n) {
		Init();
		for (int d,c,i=1;i<=n;i++)
			while (scanf("%d",&d)!=EOF && d) {
				scanf("%d",&c);
				link(i,d,c);
			}
		m=0;int x;
		while (scanf("%d",&x)!=EOF && x) q[++m]=x;
		for (int i=1;i<=m;i++) ans[i]=0;
		rt=0;sum=n;
		calroot(1,0);
		solve(rt);
		for (int i=1;i<=m;i++) {
			if (ans[i]) printf("AYE\n");
			else printf("NAY\n");
		}
		printf(".\n");
	}
	return 0;
}

  

时间: 2024-10-20 11:12:57

【poj2114】 Boatherds的相关文章

【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为止.

【Kettle】4、SQL SERVER到SQL SERVER数据转换抽取实例

1.系统版本信息 System:Windows旗舰版 Service Pack1 Kettle版本:6.1.0.1-196 JDK版本:1.8.0_72 2.连接数据库 本次实例连接数据库时使用全局变量. 2.1 创建新转换:spoon启动后,点击Ctrl+N创建新转换 2.2 在新转换界面中,右键点击DB连接,系统会弹出[数据库连接]界面. windows系统环境下,可用${}获取变量的内容. 说明: 连接名称:配置数据源使用名称.(必填) 主机名称:数据库主机IP地址,此处演示使用本地IP(

详解go语言的array和slice 【二】

上一篇  详解go语言的array和slice [一]已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多.上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变.这一篇里我会讲解到如何避免这些问题,以及迭代.和做为方法参数方面的知识点. slice的长度和容量设置为同一个值 如果在创建新的slice时我们把

【转载】C++拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #include <iostream>using namespace std;class CExample {private:     int a;public:     CExample(int b)     { a=b;}     void Show ()     {        cout<

【BZOJ】1799: [Ahoi2009]self 同类分布

[题意]给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数.1 ≤ a ≤ b ≤ 10^18 [算法]数位DP [题解] 感觉这种方法很暴力啊. 枚举数位和1~162(不能枚举0,不然会模0,相当于除0),记忆化f[pos][sum][val],sum表示当前数位和,val表示数字取模枚举的数位和. 每次sum+i和(val*10+i)%MOD转移. sum用减法优化,即记忆化(MOD-sum),但是枚举过程中都要memset,导致效率低下,记忆化效果很差. 要什么方法才能跑1.3s

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

【BZOJ4945】[Noi2017]游戏 2-SAT

[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了.然后就变成了一个2-SAT问题.假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分. 为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选

【BZOJ】2337: [HNOI2011]XOR和路径

[算法]期望+高斯消元 [题解]因为异或不能和期望同时运算,所以必须转为加乘 考虑拆位,那么对于边权为1取反,边权为0不变. E(x)表示从x出发到n的路径xor期望. 对于点x,有E(x)=Σ(1-E(y))(边权1)||E(y)(边权0)/t[x]  t[x]为x的度. 那么有n个方程,整体乘上t[x]确保精度,右项E(x)移到左边--方程可以各种变形. 每次计算完后*(1<<k)就是贡献. 逆推的原因在于n不能重复经过,而1能重复经过,所以如果计算"来源"不能计算n,

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比