首页 > 其他 > 详细

点分治练习: boatherds

时间:2016-02-13 23:11:58      阅读:450      评论:0      收藏:0      [点我收藏+]

 

【题面】

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

输入数据

n,m

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

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

输出数据

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

数据范围

对于30%的数据n<=100

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

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

 

【思路】

       树分治。

       离线存储m个询问。分治判断该m个询问是否能够出现。

       具体操作:假设当前处理第S个子树,exist[]中存储着前S-1棵子树中出现过的dis,一遍dfs得到S子树的所有dis,并判断m个询问。

       时间复杂度为O(nmlogn)

       别放了exist[0] <- 0和清空exist就好了QAQ

 

【代码】

 

 1 #include<cstdio>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 8 using namespace std;
 9 
10 const int N = 1e4+10;
11 const int M = 1e7+10;
12 
13 struct Edge {
14     int v,w;
15     Edge(int v=0,int w=0) :v(v),w(w){}
16 };
17 vector<Edge> g[N];
18 int n,m,k,q[N],ans[N];
19 int root,size,siz[N],f[N],dis[N],vis[N],tmp[N],l1,l2,exist[M];
20 
21 void getroot(int u,int fa) {
22     siz[u]=1; f[u]=0; exist[0]=1;
23     for(int i=0;i<g[u].size();i++) {
24         int v=g[u][i].v;
25         if(v!=fa && !vis[v]) {
26             getroot(v,u);
27             siz[u]+=siz[v];
28             if(siz[v]>f[u]) f[u]=siz[v];
29         }
30     }
31     f[u]=max(f[u],size-siz[u]);
32     if(f[u]<f[root]) root=u;
33 }
34 void dfs(int u,int fa) {
35     tmp[++l1]=dis[u];
36     for(int i=0;i<g[u].size();i++) {
37         int v=g[u][i].v;
38         if(v!=fa && !vis[v]) {
39             dis[v]=dis[u]+g[u][i].w;
40             dfs(v,u);
41         }
42     }
43 }
44 void solve(int u) {
45     vis[u]=1;
46     l1=l2=0;
47     for(int i=0;i<g[u].size();i++) {
48         int v=g[u][i].v;
49         l2=l1+1;
50         if(!vis[v]) {
51             dis[v]=g[u][i].w;
52             dfs(v,u);
53             FOR(i,l2,l1) FOR(j,1,m) 
54                 if(q[j]>=tmp[i] && exist[q[j]-tmp[i]]) ans[j]=1;
55             FOR(i,l2,l1) exist[tmp[i]]=1;
56         }
57     }
58     FOR(i,1,l1) exist[tmp[i]]=0;
59     for(int i=0;i<g[u].size();i++) {
60         int v=g[u][i].v;
61         if(!vis[v]) {
62             root=0; getroot(u,-1);
63             size=siz[v]; solve(root);
64         }
65     }
66 }
67 
68 void read(int& x) {
69     char c=getchar(); int f=1; x=0;
70     while(!isdigit(c)){if(c==-) c=-1; c=getchar();}
71     while(isdigit(c)) x=x*10+c-0,c=getchar();
72     x*=f;
73 }
74 int main() {
75     //freopen("in.in","r",stdin);
76     //freopen("out.out","w",stdout);
77     read(n),read(m);
78     int u,v,w;
79     FOR(i,1,n-1) {
80         read(u),read(v),read(w);
81         g[u].push_back(Edge(v,w));
82         g[v].push_back(Edge(u,w));
83     }
84     FOR(i,1,m) read(q[i]);
85     size=n; f[0]=1e9; root=0;
86     getroot(1,-1); solve(root);
87     FOR(i,1,m) if(ans[i]) puts("AYE"); else puts("NAY");
88     return 0;
89 }

 

点分治练习: boatherds

原文:http://www.cnblogs.com/lidaxin/p/5188352.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!