POJ 2114 Boatherds (树上点分治)

来源:互联网 发布:js div height 编辑:程序博客网 时间:2024/05/16 06:55

题目地址:POJ 2114
点分治水题。只是把距离小于等于k改成了等于k。稍微加一点处理就可以了。
代码如下:

#include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>#include <time.h>using namespace std;#define LL __int64#define pi acos(-1.0)//#pragma comment(linker, "/STACK:1024000000")const int mod=1e9+7;const int INF=0x3f3f3f3f;const double eqs=1e-9;const int MAXN=20000+10;int head[MAXN], cnt, tot, tt, min1, n, root;int siz[MAXN], d[MAXN], dep[MAXN], ans[MAXN], q[MAXN], vis[MAXN];int c[MAXN], dp[MAXN];struct node{        int v, w, next;} edge[MAXN<<1];void add(int u, int v, int w){        edge[cnt].v=v;        edge[cnt].w=w;        edge[cnt].next=head[u];        head[u]=cnt++;}void init(){        memset(head,-1,sizeof(head));        cnt=tot=tt=0;        memset(vis,0,sizeof(vis));        memset(ans,0,sizeof(ans));}void getroot(int u, int fa, int s){        siz[u]=1;        int max1=0;        for(int i=head[u];i!=-1;i=edge[i].next){                int v=edge[i].v;                if(v==fa||vis[v]) continue ;                getroot(v,u,s);                siz[u]+=siz[v];                max1=max(max1,siz[v]);        }        max1=max(max1,s-siz[u]);        if(min1>max1){                root=u;                min1=max1;        }}void getdep(int u, int fa){        d[tot++]=dep[u];        siz[u]=1;        for(int i=head[u];i!=-1;i=edge[i].next){                int v=edge[i].v;                if(v==fa||vis[v]) continue ;                dep[v]=dep[u]+edge[i].w;                getdep(v,u);                siz[u]+=siz[v];        }}void Cal(int u, int len, int f){        tot=0;        dep[u]=len;        getdep(u,-1);        sort(d,d+tot);        int i, j, k, y=0;        c[0]=d[0];        dp[0]=1;        for(i=1;i<tot;i++){                if(d[i]!=d[i-1]){                        dp[++y]=1;                        c[y]=d[i];                }                else{                        dp[y]++;                }        }        for(i=0;i<tt;i++){                k=y;                for(j=0;j<=y;j++){                        while(c[j]+c[k]>q[i]&&k>j) k--;                        if(k==j&&c[j]+c[k]==q[i]) ans[i]+=f*(dp[j]*(dp[j]-1)/2);                        if(k<=j) break;                        if(c[j]+c[k]==q[i])  ans[i]+=f*dp[j]*dp[k];                }        }}void work(int u){        Cal(u,0,1);        vis[u]=1;        for(int i=head[u];i!=-1;i=edge[i].next){                int v=edge[i].v;                if(vis[v]) continue ;                Cal(v,edge[i].w,-1);                min1=INF;                getroot(v,-1,siz[v]);                work(root);        }}int main(){        int i, v, w, j, x;        while(scanf("%d",&n)!=EOF&&n){                init();                for(i=1;i<=n;i++){                        while(scanf("%d",&v)!=EOF&&v){                                scanf("%d",&w);                                add(i,v,w);                                add(v,i,w);                        }                }                while(scanf("%d",&x)!=EOF&&x) q[tt++]=x;                min1=INF;                getroot(1,-1,n);                work(root);                for(i=0;i<tt;i++){                        if(ans[i]) puts("AYE");                        else puts("NAY");                }                puts(".");        }        return 0;}
1 0