【poj2114】点分治(离线)

boatherds 2s 64M by czy

求一颗树上距离为K的点对是否存在

输入数据

n,m

接下来n-1条边a,b,c描述a到b有一条长度为c的路径

接下来m行每行询问一个K

输出数据

对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NYE”(不包含引号)

数据范围

对于30%的数据n<=100

对于60%的数据n<=1000,m<=50

对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000


 

点分治。

但是每次询问会超时,所以需要离线。

就把K都存起来,每次询问的时候都for一遍K。

代码:

  1 // #pragma comment(linker,"/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 const int N=10010;
 10 int n,m,sl,kl,tl,vl,len,first[N],mark[N],s[N],t[N],d[N],size[N],K[N],ans[N];//,v[N];
 11 bool v[10000010];
 12 struct node{
 13     int x,y,d,next;
 14 }a[2*N];
 15 
 16 bool cmp(int x,int y){return x<y;}
 17 
 18 void ins(int x,int y,int d)
 19 {
 20     a[++len].x=x;a[len].y=y;a[len].d=d;
 21     a[len].next=first[x];first[x]=len;
 22 }
 23 
 24 void find_root(int x,int fa,int tot,int &root)
 25 {
 26     size[x]=1;
 27     bool bk=1;
 28     for(int i=first[x];i;i=a[i].next)
 29     {
 30         int y=a[i].y;
 31         if(y==fa || mark[y]) continue;
 32         find_root(y,x,tot,root);
 33         size[x]+=size[y];
 34         if(2*size[y]>tot) bk=0;
 35     }
 36     if(bk && 2*(tot-size[x])<=tot) root=x;
 37 }
 38 
 39 void DFS(int x,int fa)
 40 {
 41     for(int i=1;i<=kl;i++)
 42     {
 43         if(K[i]>=d[x] && v[K[i]-d[x]]) ans[i]=1;
 44     }
 45     // if(ans==1) return ;
 46     t[++tl]=d[x];
 47     size[x]=1;
 48     for(int i=first[x];i;i=a[i].next)
 49     {
 50         int y=a[i].y;
 51         if(y==fa || mark[y]) continue;
 52         d[y]=d[x]+a[i].d;
 53         DFS(y,x);
 54         size[x]+=size[y];
 55     }
 56 }
 57 
 58 void dfs(int x,int tot)
 59 {
 60     find_root(x,0,tot,x);
 61     v[0]=1;sl=0;//ssl=0;
 62     // s[++sl]=x;
 63     mark[x]=1;
 64     for(int i=first[x];i;i=a[i].next)
 65     {
 66         int y=a[i].y;
 67         if(mark[y]) continue;
 68         tl=0;d[y]=a[i].d;
 69         DFS(y,x);
 70         // if(ans==1) break;
 71         for(int j=1;j<=tl;j++) v[t[j]]=1,s[++sl]=t[j];
 72     }
 73     for(int i=1;i<=sl;i++) v[s[i]]=0;
 74     // if(ans==1) return ;
 75     for(int i=first[x];i;i=a[i].next)
 76     {
 77         int y=a[i].y;
 78         if(mark[y]) continue;
 79         dfs(y,size[y]);
 80     }
 81 }
 82 
 83 int main()
 84 {
 85     // freopen("a.in","r",stdin);
 86     freopen("boatherds.in","r",stdin);
 87     freopen("boatherds.out","w",stdout);
 88     scanf("%d%d",&n,&kl);
 89     len=0;
 90     memset(v,0,sizeof(v));
 91     memset(first,0,sizeof(first));
 92     for(int i=1;i<n;i++)
 93     {
 94         int x,y,c;
 95         scanf("%d%d%d",&x,&y,&c);
 96         ins(x,y,c);
 97         ins(y,x,c);
 98     }
 99     for(int i=1;i<=kl;i++) scanf("%d",&K[i]);
100     memset(ans,0,sizeof(ans));
101     dfs(1,n);
102     for(int i=1;i<=kl;i++)
103     {
104         if(ans[i]) printf("AYE\n");
105         else printf("NAY\n");
106     }
107     return 0;
108 }

 

posted @ 2016-11-10 15:56  拦路雨偏似雪花  阅读(316)  评论(0编辑  收藏  举报