题意:给定一棵树,随后给出不多于100个查询k,问树上是否存在恰等于k的路径。
思路:对每一个k做一遍树分治,与1714的区别就是update函数的写法,此题要求的是路径距离恰等于k的条数。(其中判断条件j>i没加到时tle了两天,苦苦debug才AC)。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define clr(s,t) memset(s,t,sizeof(s))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define N 10005
struct edge{
int y,w,next;
}e[N<<1];
int first[N],used[N],son[N],tnum[N],q[N],dis[N];
int res;
int top,n,m,k,len,size,root;
void init(){
res = len = 0;
clr(used, 0);
tnum[0] = N;
}
void add(int x,int y,int w){
e[top].y = y;
e[top].w = w;
e[top].next = first[x];
first[x] = top++;
}
int cmp(const void* a,const void* b){
return (*(int*)a) - (*(int*)b);
}
void getroot(int x,int fa){
int i,y;
son[x] = 1;
tnum[x] = 0;
for(i = first[x];i!=-1;i=e[i].next){
y = e[i].y;
if(!used[y] && y!=fa){
getroot(y, x);
son[x] += son[y];
tnum[x] = max(tnum[x], son[y]);
}
}
tnum[x] = max(tnum[x], size-son[x]);
if(tnum[x] < tnum[root])
root = x;
}
void getdis(int x,int fa){
int i,y;
q[len++] = dis[x];
son[x] = 1;
for(i = first[x];i!=-1;i=e[i].next){
y = e[i].y;
if(!used[y] && y!=fa){
dis[y] = dis[x]+e[i].w;
getdis(y, x);
son[x] += son[y];
}
}
}
int update(){
int i,j,a,b,sum=0;
qsort(q, len, sizeof(int), cmp);
for(i = 0,j = len-1;;i++){
while(j>i&&q[i]+q[j]>k)//没有加j>i这句tle了无数次
j--;
if(i>=j)
break;
if(q[i]+q[j]<k)
continue;
if(q[i] == q[j]){
sum += (j-i)*(j-i+1)/2;
break;
}
a = i,b = j;
while(q[a] == q[i])
a++;
while(q[b] == q[j])
b--;
sum += (a-i)*(j-b);
i = a-1;
j = b;
}
return sum;
}
void tdc(int x){
int i,y;
getroot(x,root=0);
dis[root] = len = 0;
getdis(root,0);
res += update();
used[root] = 1;
for(i = first[root];i!=-1;i=e[i].next){
y = e[i].y;
if(!used[y]){
len = 0;
dis[y] = e[i].w;
getdis(y, root);
res -= update();//减去root上的长度为k的路径而实际上这两个点在一课子树中(即含有重复边)
size = son[y];
tdc(y);
}
}
}
int main(){
while(scanf("%d",&n) && n){
int i,j,w;
clr(first, -1);
top = 0;
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){
init();
size = n;
tdc(1);
if(res)
printf("AYE\n");
else
printf("NAY\n");
}
printf(".\n");
}
return 0;
}