首页 > 代码库 > 【poj2114】 Boatherds

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

  

【poj2114】 Boatherds