1316: 树上的询问(点分治)

Posted HWIM

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1316: 树上的询问(点分治)相关的知识,希望对你有一定的参考价值。

1316: 树上的询问

链接

 

分析

  每次查找出重心(去掉重心后的最大的联通块最小,保证复杂度),然后统计过重心的路径中有没有长度等于len的。

  统计时,由于必须要过重心,不能是同一棵子树中的。可以挨个遍历每棵子树,然后统计即可。

  判断时,用set查找一下即可。

代码

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cctype>
  4 #include<set>
  5  
  6 using namespace std;
  7  
  8 const int N = 10010;
  9  
 10 struct Edge{
 11     int to,nxt,w;
 12     Edge() {}
 13     Edge(int a,int b,int c) {to = a,w = b,nxt = c;}
 14 }e[N<<1];
 15 int A[N],q[N],ans[N],dis[N],deth[N],head[N],siz[N];
 16 int tot,Root,Size,Cnt,Num = 1e9,n,m;
 17 bool vis[N];
 18 set<int>s;
 19  
 20 inline int read() {
 21     int x = 0,f = 1;char ch=getchar();
 22     for (; !isdigit(ch); ch=getchar()) if(ch==-)f=-1;
 23     for (; isdigit(ch); ch=getchar()) x=x*10+ch-0;
 24     return x*f;
 25 }
 26 void add_edge(int u,int v,int w) {
 27     e[++tot] = Edge(v,w,head[u]);head[u] = tot;
 28     e[++tot] = Edge(u,w,head[v]);head[v] = tot;
 29 }
 30 void getRoot(int u,int fa) {
 31     siz[u] = 1;
 32     int mx = 0;
 33     for (int i=head[u]; i; i=e[i].nxt) {
 34         int v = e[i].to;
 35         if (v == fa || vis[v]) continue;
 36         getRoot(v,u);
 37         siz[u] += siz[v];
 38         mx = max(siz[v],mx);
 39     }
 40     mx = max(mx,Size-siz[u]);
 41     if (mx < Num) Root = u,Num = mx;
 42 }   
 43 void dfs(int u,int fa) {
 44     A[++Cnt] = dis[u];
 45     for (int i=head[u]; i; i=e[i].nxt) {
 46         int v = e[i].to;
 47         if (v == fa || vis[v]) continue;
 48         dis[v] = dis[u] + e[i].w;
 49         dfs(v,u);
 50     }
 51 }
 52 void calcc(int u) {
 53     s.clear();
 54     s.insert(0);
 55     dis[u] = 0;
 56     for (int i=head[u]; i; i=e[i].nxt) {
 57         int v = e[i].to;
 58         if (vis[v]) continue;
 59         Cnt = 0;
 60         dis[v] = e[i].w;
 61         dfs(v,u);
 62         for (int j=1; j<=Cnt; ++j) {
 63             for (int k=1; k<=m; ++k) {
 64                 if (ans[k]) continue;
 65                 if (s.find(q[k]-A[j])!=s.end()) ans[k] = 1;
 66             }
 67         }
 68         for (int j=1; j<=Cnt; ++j) s.insert(A[j]);
 69     }
 70 }
 71 void solve(int u) {
 72     vis[u] =  true;
 73     calcc(u);
 74     for (int i=head[u]; i; i=e[i].nxt) {
 75         int v = e[i].to;
 76         if (vis[v]) continue;
 77         Size = siz[v];Num = 1e9;Root = 0;
 78         getRoot(v,0);
 79         solve(Root);
 80     }
 81 }
 82 int main() {
 83     n = read(),m = read();
 84     for (int u,v,w,i=1; i<n; ++i) {
 85         u = read(),v = read(),w = read();
 86         add_edge(u,v,w);
 87     }
 88     for (int i=1; i<=m; ++i) {
 89         q[i] = read();
 90         if (!q[i]) ans[i] = 1;
 91     }
 92     Size = n;
 93     Num = 1e9;
 94     getRoot(1,0);
 95     solve(Root);
 96     for (int i=1; i<=m; ++i) 
 97         if (ans[i]) puts("Yes");
 98         else puts("No");
 99     return 0;
100 }

 

以上是关于1316: 树上的询问(点分治)的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj1316]树上的询问_点分治

BZOJ_1316_树上的询问_点分治

BZOJ1316树上的询问 点分治+set

bzoj1316树上的询问 树的点分治+STL-set

[POJ 1316] 树上的询问

[bzoj1316] 树上的询问