[POJ 1316] 树上的询问

[题目链接]

        https://www.lydsy.com/JudgeOnline/problem.php?id=1316

[算法]

          点分治 

          由于边权较大,笔者在计算时使用了STL-set

          注意当询问为0时,要输出"Yes"

[代码]

      

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
#define MAXQ 110

struct Edge
{
    int to,w,nxt;
} e[MAXN<<1];

int i,n,q,tot,root,u,v,w,len;
int size[MAXN],head[MAXN],weight[MAXN],sum[MAXN],val[MAXN],a[MAXQ];
bool visited[MAXN],ans[MAXQ];

inline void addedge(int u,int v,int w)
{
    tot++;
    e[tot] = (Edge){v,w,head[u]};
    head[u] = tot;
}
inline void getroot(int u,int fa,int total)
{
    int i,v;
    size[u] = 1;
    weight[u] = 0;
    for (i = head[u]; i; i = e[i].nxt)
    {
        v = e[i].to;
        if (fa != v && !visited[v])
        {
            getroot(v,u,total);
            size[u] += size[v];
            weight[u] = max(weight[u],size[v]);
        }
    }
    weight[u] = max(weight[u],total - size[u]);
    if (weight[u] < weight[root]) root = u;
}
inline void dfs(int u,int fa)
{
    int i,v,w;
    val[++len] = sum[u]; 
    for (i = head[u]; i; i = e[i].nxt)
    {
        v = e[i].to;
        w = e[i].w;
        if (v != fa && !visited[v]) 
        {
            sum[v] = sum[u] + w;
            dfs(v,u); 
        }
    }
}
inline void calc(int u)
{
    int i,j,k,v,w;
    set< int > s;
    s.clear();
    s.insert(0);
    for (i = head[u]; i; i = e[i].nxt)
    {
        v = e[i].to;
        w = e[i].w;
        if (!visited[v])
        {
            sum[v] = w;
            len = 0;
            dfs(v,u);
            for (j = 1; j <= len; j++)
            {
                for (k = 1; k <= q; k++)
                {
                    if (s.find(a[k] - val[j]) != s.end())
                        ans[k] = true;
                }
            }
            for (j = 1; j <= len; j++) s.insert(val[j]);
        }
    }
}
inline void work(int u)
{
    int i,v;
    visited[u] = true;
    calc(u);    
    for (i = head[u]; i; i = e[i].nxt)
    {
        v = e[i].to;
        if (!visited[v])
        {
            root = 0;
            getroot(v,0,size[v]);
            work(root);
        }
    }
}

int main()
{
    
    
    scanf("%d%d",&n,&q);
    for (i = 1; i < n; i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);        
    }
    for (i = 1; i <= q; i++) scanf("%d",&a[i]);
    root = 0;
    size[0] = weight[0] = n;
    getroot(1,0,n);
    work(root);
    for (i = 1; i <= q; i++) printf((ans[i] || a[i] == 0) ? "Yes\n" : "No\n");

    return 0;
}

 

posted @ 2018-07-18 11:58  evenbao  阅读(128)  评论(0编辑  收藏  举报