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;
        }
    }
    
    
  • 相关阅读:
    TFS对签入文件忽略设置,解决pdb弹出警告
    利用MSSQL对不经常使用的表进行依赖缓存
    IIS 使用多个https和通配证书解决方案
    传递参数安全验证代码示例
    利用GetType反射方法再调用方法进行传递参数实现调用
    ms10_002 IE浏览器漏洞
    ms17-010漏洞复现
    ms08-067漏洞复现
    tomcat使用log4j管理日志
    Popen No such file or directory 错误
  • 原文地址:https://www.cnblogs.com/mollnn/p/13267069.html
Copyright © 2011-2022 走看看