题意:给定一棵树,随后给出不多于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; }