点分治
Posted amitherblogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点分治相关的知识,希望对你有一定的参考价值。
#include<stdio.h> #include<algorithm> #include<iostream> using namespace std; const int maxn=1e4+5; const int inf=0x3f3f3f3f; struct edge{ int v, next; int w; }e[maxn*2]; int head[maxn]; int total=0; void addedge(int u, int v, int w){ total++; e[total].v=v; e[total].w=w; e[total].next=head[u]; head[u]=total; } int sim[maxn];//size of the tree i int mxson[maxn]; int root; int MX=0; int Smer; bool vis[maxn]; void getroot(int u,int fa) { sim[u] = 1; mxson[u] = 0; for(int i = head[u];i;i = e[i].next) { int v = e[i].v; if(vis[v]||v == fa)continue; getroot(v,u); sim[u] = sim[u] + sim[v]; mxson[u] = max(mxson[u],sim[v]); } mxson[u] = max(mxson[u],Smer - sim[u]); if(mxson[u]<MX){ root = u; MX = mxson[u]; } } int dist[maxn]; int ans[10000005]; void query(int& cnt, int u, int fa, int len){//以u为根,树上节点到u的长度 dist[++cnt]=len; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(vis[v]||v==fa)continue; query(cnt, v, u, e[i].w+len); } } void solve(int u, int len, int key){ int cnt=0; query(cnt, u, 0, len); if(key){ for(int i=1;i<cnt;i++){ for(int j=i+1;j<=cnt;j++){ ans[dist[i]+dist[j]]++; } } }else{ for(int i=1;i<cnt;i++){ for(int j=i+1;j<=cnt;j++){ ans[dist[i]+dist[j]]--; } } } } void Divide(int u) { solve(u, 0, 1);//算上所有的 vis[u] = true; for(int i = head[u];i;i = e[i].next) { int v = e[i].v; if(vis[v])continue; solve(v,e[i].w, 0);//减去相同链的 Smer = sim[v]; root = 0;MX = inf; getroot(v,0);//get subtree‘s root Divide(root); } return; } int main() { freopen("in.txt","r",stdin); int n,m; scanf("%d%d",&n,&m); int cnt=n-1; while(cnt--){ int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } MX=inf; Smer=n; getroot(1, 0); Divide(root); while(m--){ int k; scanf("%d",&k); if(ans[k])printf("AYE "); else printf("NAY "); } }
#include<stdio.h>#include<algorithm>#include<iostream>using namespace std;const int maxn=1e4+5;const int inf=0x3f3f3f3f;struct edge{int v, next;int w;}e[maxn*2];int head[maxn];int total=0;void addedge(int u, int v, int w){total++;e[total].v=v;e[total].w=w;e[total].next=head[u];head[u]=total;}int sim[maxn];//size of the tree iint mxson[maxn];int root;int MX=0;int Smer;bool vis[maxn];void getroot(int u,int fa){sim[u] = 1; mxson[u] = 0;for(int i = head[u];i;i = e[i].next) { int v = e[i].v; if(vis[v]||v == fa)continue; getroot(v,u); sim[u] = sim[u] + sim[v]; mxson[u] = max(mxson[u],sim[v]); } mxson[u] = max(mxson[u],Smer - sim[u]);if(mxson[u]<MX){ root = u; MX = mxson[u];}}int dist[maxn];int ans[10000005];void query(int& cnt, int u, int fa, int len){//以u为根,树上节点到u的长度 dist[++cnt]=len;for(int i=head[u];i;i=e[i].next){int v=e[i].v;if(vis[v]||v==fa)continue;query(cnt, v, u, e[i].w+len);}}void solve(int u, int len, int key){int cnt=0;query(cnt, u, 0, len);if(key){for(int i=1;i<cnt;i++){for(int j=i+1;j<=cnt;j++){ans[dist[i]+dist[j]]++;}}}else{for(int i=1;i<cnt;i++){for(int j=i+1;j<=cnt;j++){ans[dist[i]+dist[j]]--;}}}}void Divide(int u){ solve(u, 0, 1);//算上所有的 vis[u] = true; for(int i = head[u];i;i = e[i].next) { int v = e[i].v; if(vis[v])continue; solve(v,e[i].w, 0);//减去相同链的 Smer = sim[v]; root = 0;MX = inf; getroot(v,0);//get subtree‘s root Divide(root); } return;}int main(){freopen("in.txt","r",stdin);int n,m;scanf("%d%d",&n,&m);int cnt=n-1;while(cnt--){int u,v,w;scanf("%d%d%d",&u,&v,&w);addedge(u,v,w);addedge(v,u,w);}MX=inf;Smer=n;getroot(1, 0);Divide(root);while(m--){int k;scanf("%d",&k);if(ans[k])printf("AYE ");else printf("NAY ");}}
以上是关于点分治的主要内容,如果未能解决你的问题,请参考以下文章