【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;
}

  

posted @ 2016-10-05 17:12  MashiroSky  阅读(261)  评论(0编辑  收藏  举报