zoukankan      html  css  js  c++  java
  • [BZOJ1316] 树上的询问

    Description

    一棵 (n) 个点的带权有根树,有 (p) 个询问,每次询问树中是否存在一条长度为 (len) 的路径。(n le 10^4, p le 10^2)

    Solution

    点分治板子,用 set 维护,注意特判 (k=0) 的情况

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 10005;
    
    vector<pair<int,int> > g[N];
    // k : query
    int dis[N],siz[N],msiz[N],n,m,k[N],ans[N],u[N];
    vector <int> st;
    vector <int> wl;
    
    void dfs1(int p,int from)
    {
        siz[p]=1;
        msiz[p]=0;
        st.push_back(p);
        for(pair<int,int> pr:g[p])
        {
            int q=pr.first, w=pr.second;
            if(q!=from && u[q]==0)
            {
                dfs1(q,p);
                siz[p]+=siz[q];
                msiz[p]=max(msiz[p],siz[q]);
            }
        }
    }
    
    void dfs2(int p,int from)
    {
        for(pair<int,int> pr:g[p])
        {
            int q=pr.first, w=pr.second;
            if(q!=from && u[q]==0)
            {
                dis[q]=dis[p]+w;
                dfs2(q,p);
            }
        }
    }
    
    multiset <int> buc;
    
    void dfs3(int p,int from)
    {
        // Process each query
        for(int i=1; i<=m; i++)
        {
            if(buc.find(k[i]-dis[p]) != buc.end()) ans[i]=1;
        }
        for(pair<int,int> pr:g[p])
        {
            int q=pr.first, w=pr.second;
            if(q!=from && u[q]==0)
            {
                dfs3(q,p);
            }
        }
        wl.push_back(p);
    }
    
    int findroot(int p)
    {
        st.clear();
        dfs1(p,0);
        int r=0,rv=1e+9;
        for(int i=0; i<st.size(); i++)
        {
            msiz[st[i]]=max(msiz[st[i]],siz[p]-siz[st[i]]);
            if(msiz[st[i]]<rv) r=st[i],rv=msiz[st[i]];
        }
        return r;
    }
    
    void calc(int p)
    {
        dis[p]=0;
        dfs2(p,0);
        buc.clear();
        buc.insert(0);
        for(pair<int,int> pr:g[p])
        {
            // Process each subtree
            int q=pr.first, w=pr.second;
            if(u[q]==0)
            {
                dfs3(q,0);
                // wl: all nodes in this subtree
                for(int j:wl)
                {
                    buc.insert(dis[j]);
                }
                wl.clear();
            }
        }
    }
    
    void solve(int p)
    {
        int r=findroot(p);
        u[r]=1;
        calc(r);
        for(pair<int,int> pr:g[r])
        {
            int q=pr.first, w=pr.second;
            if(u[q]==0)
            {
                solve(q);
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1; i<n; i++)
        {
            int t1,t2,t3;
            cin>>t1>>t2>>t3;
            g[t1].push_back({t2,t3});
            g[t2].push_back({t1,t3});
        }
        for(int i=1; i<=m; i++) cin>>k[i];
        solve(1);
        for(int i=1; i<=m; i++)
        {
            cout<<(ans[i]||!k[i]?"Yes":"No")<<endl;
        }
    }
    
    
  • 相关阅读:
    ZJCTF预赛一个.py的逆向题
    if(a)是什么意思
    整理OD一些快捷键和零碎知识点
    NSCTF-Reverse02 超级详细且简单的办法搞定
    CTF实验吧——证明自己吧
    Beat our dice game and get the flag 击败我们的骰子游戏拿到旗子
    CTF-Keylead(ASIS CTF 2015)
    【第三届强网杯】两道杂项题的wp
    【实验吧】该题不简单——writeup
    嵩天老师python网课爬虫实例1的问题和解决方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/13264294.html
Copyright © 2011-2022 走看看