zoukankan      html  css  js  c++  java
  • 点分治模板

    [BZOJ1316]

    由于之前板子写得太烂了,今天把它重新整理改进了一下

    vis[] 表示每个点是否已经当过根,所以注意 dfs,findroot 函数的计算过程中是不会对 vis 进行修改的

    修改时只需要考虑对 dfssolve 中的有关位置进行修改即可,其它部分基本不变

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    #define foradj(p) for(pair<int,int> pr:g[p])
    #define unpii(q,w) int q=pr.first, w=pr.second;
    const int N = 10005;
    
    vector <pair<int,int> > g[N];
    int dis[N],siz[N],n,m,t1,t2,t3,k[N],ans[N],vis[N],sum,rt,rtval;
    vector<int> st,wl;
    set<int> s;
    
    void findroot(int p,int ff)
    {
        siz[p]=1;
        int mx=0;
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q] && q!=ff)
            {
                findroot(q,p);
                siz[p]+=siz[q];
                mx=max(mx,siz[q]);
            }
        }
        mx=max(mx,sum-siz[p]);
        if(mx<rtval) rtval=mx, rt=p;
    }
    
    void dfs(int p,int ff)
    {
        for(int i=1;i<=m;i++)
        {
            ans[i]|=s.count(k[i]-dis[p]);
            st.push_back(dis[p]);
        }
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q] && q!=ff)
            {
                dis[q]=dis[p]+w;
                dfs(q,p);
            }
        }
    }
    
    void solve(int p)
    {
        vis[p]=1;
        s.clear();
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q])
            {
                dis[q]=w;
                dfs(q,p);
                for(int i:st) s.insert(i);
                st.clear();
            }
        }
        for(int i=1;i<=m;i++)
        {
            ans[i]|=s.count(k[i]);
        }
        foradj(p)
        {
            unpii(q,w);
            if(!vis[q])
            {
                sum=siz[q];
                rtval=1e18;
                findroot(q,0);
                solve(rt);
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<n;i++)
        {
            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];
        }
        sum=n;
        rtval=1e18;
        findroot(1,0);
        solve(rt);
        for(int i=1;i<=m;i++)
        {
            if(ans[i] || !k[i]) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
    }
    
    
  • 相关阅读:
    Sexy Beach PR 汉化补丁+入门教程
    [Unity3D]Script 脚本全部编译器属性具体解释
    图论--最小生成树和最短路1
    软件设计师之路总结~引——时间的温度
    BZOJ1441: Min
    BZOJ1602: [Usaco2008 Oct]牧场行走
    BZOJ1600: [Usaco2008 Oct]建造栅栏
    BZOJ1599: [Usaco2008 Oct]笨重的石子
    BZOJ1601: [Usaco2008 Oct]灌水
    BZOJ1058: [ZJOI2007]报表统计
  • 原文地址:https://www.cnblogs.com/mollnn/p/13267069.html
Copyright © 2011-2022 走看看