zoukankan      html  css  js  c++  java
  • 洛谷 P3806 (点分治)

    题目:https://www.luogu.org/problem/P3806

    题意:一棵树,下面有q个询问,问是否有距离为k的点对

    思路:牵扯到树上路径的题都是一般都是点分治,我们可以算出所有的路径长度然后保留下来,点分治无非就是几步一直递归,点分治就是在树上递归

    1,找树的重心

    2,算出所有点到重心距离,找出当前重心的所有合法路径

    3,递归到子树

    然后反复执行这三步

    其实点分治唯一思考的地方就是  solve函数,其他都是一样的

    https://www.cnblogs.com/guoshaoyang/p/10994997.html

    https://www.cnblogs.com/PinkRabbit/p/8593080.html

    #include<bits/stdc++.h>
    #define maxn 100005
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    vector<pair<ll,ll> > mp[maxn];//存下图 
    bool vis[maxn];//标记曾经使用过的重心 
    ll maxsize[maxn],dis[maxn],d[maxn];//maxsize 当前节点的最大子树 
    ll siz[maxn],e[maxn];// dis 到重心的距离  d 出现过的距离 
    ll n,m,rt,sum,qe;  // siz 当前节点的子树个数  e 出现的距离  rt代表当前重心 
    void find(ll x,ll f){//找出重心 
        siz[x]=1;
        maxsize[x]=0;
        for(int i=0;i<mp[x].size();i++){
            pair<ll,ll> q=mp[x][i];
            if(q.first==f||vis[q.first]) continue;//vis数组标记曾经使用过的重心 
            find(q.first,x);
            siz[x]+=siz[q.first];
            maxsize[x]=max(maxsize[x],siz[q.first]); 
        } 
        maxsize[x]=max(maxsize[x],sum-siz[x]);//节点总数减去当前的子树数=以当前节点为根的父亲点子树数 
        if(maxsize[x]<maxsize[rt]){
            rt=x;
        } 
    }
    void get_dis(ll x,ll f,ll len){//得到每个点到重心的距离
        if(len<=1e7){
            e[++qe]=len;
        } 
        for(int i=0;i<mp[x].size();i++){
            pair<ll,ll> q=mp[x][i];
            if(q.first==f||vis[q.first]) continue;
            dis[q.first]=dis[x]+len;
            get_dis(q.first,x,len+q.second);
        }    
    }
    void solve(ll x,ll len,ll w){
        qe=0;
        dis[x]=len;
        get_dis(x,0,len);
        for(int i=1;i<=qe;i++){
            for(int j=1;j<=qe;j++){
                if(i!=j){
                    d[e[i]+e[j]]+=w;
                }
            }
        }
    }
    void divide(ll x){//循环执行三步
        solve(x,0,1);
        vis[x]=1;
        for(int i=0;i<mp[x].size();i++){
            pair<ll,ll> q=mp[x][i];
            if(vis[q.first]) continue;
            solve(q.first,q.second,-1);
            sum=siz[q.first];
            rt=0;
            maxsize[rt]=mod;
            find(q.first,x);
            divide(rt);
        }
    }
    int main(){
        cin>>n>>m;
        ll a,b,c;
        for(int i=0;i<n-1;i++){
            cin>>a>>b>>c;
            mp[a].push_back(make_pair(b,c));
            mp[b].push_back(make_pair(a,c));
        }
        sum=n;//当前节点数 
        rt=0;
        maxsize[0]=mod;//置初值 
        find(1,0);
        divide(rt);
        while(m--){
            cin>>a;
            if(d[a]){
                printf("AYE
    ");
            }
            else{
                printf("NAY
    ");
            }
        }
    } 
  • 相关阅读:
    Node.js 调用 restful webservice
    Node.js的集群功能以及在Express的配置
    Node.js 连接mySQL程序
    客户端连接Redis
    缓存的压力测试脚本
    搭建redis集群环境
    编译EXE文件的时候pcap编译不进去。 pyinstaller pcap pypcap 报错
    selenium(五)伪造浏览器
    selenium(四)操作cookie,伪造cookie
    selenium(三)浏览器操作
  • 原文地址:https://www.cnblogs.com/Lis-/p/11347684.html
Copyright © 2011-2022 走看看