点分治练习: boatherds
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点分治练习: boatherds相关的知识,希望对你有一定的参考价值。
【题面】
求一颗树上距离为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的主要内容,如果未能解决你的问题,请参考以下文章