• POJ


    题目:https://vjudge.net/contest/307753#problem/D

    题意:给你一棵树,让你求出一个点,让他的最大子树的节点数尽量小

    思路:最大子树节点数尽量小,一看就是树的重心, 然后随便套个原来的点分治模板即可

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream> 
    #include<vector>
    #define maxn 100005
    #define mod 1e19
    using namespace std;
    typedef long long ll;
    ll da;
    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;
        }
        else if(maxsize[x]==maxsize[rt]&&rt>x){
            rt=x;
        } 
    }
    void get_dis(ll x,ll f,ll len){
        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);
        }    
    }
    ll solve(ll x,ll len){
        ll ee=0;
        qe=0;
        dis[x]=len;
        get_dis(x,0,len);
        sort(e+1,e+qe+1);
        ll l=1,r=qe;
        while(l<r){
            if(e[l]+e[r]<=m){
                ee+=r-l;
                l++;
            }
            else{
                r--;
            }
        }
        return ee;
    }
    void divide(ll x){
        da+=solve(x,0);
        vis[x]=1;
        for(int i=0;i<mp[x].size();i++){
            pair<ll,ll> q=mp[x][i];
            if(vis[q.first]) continue;
            da-=solve(q.first,q.second);
            sum=siz[q.first];
            rt=0;
            maxsize[rt]=mod;
            find(q.first,x);
            divide(rt);
        }
    }
    void init(){
        da=0;
        for(int i=0;i<=n;i++) mp[i].clear();
        for(int i=0;i<=n;i++) vis[i]=0;
    } 
    int main(){
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lld",&n);
            ll a,b,c;
            init();
            for(int i=0;i<n-1;i++){
                scanf("%lld%lld",&a,&b);
                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);
            printf("%lld %lld
    ",rt,maxsize[rt]);
        }
    } 
  • 相关阅读:
    使用idea进行远程调试
    map根据属性排序、取出map前n个
    编写shell脚本一键启动 重启 停止springboot jar包
    IDEA给类和方法配置注释模板(参数换行显示)
    springboot文件上传报错
    WebMvcConfigurer 与 WebMvcConfigurationSupport避坑指南
    WebMvcConfigurerAdapter详解和过时后的替代方案
    springboot上传文件过大,全局异常捕获,客户端没有返回值
    javascript中Math.random()产生随机数总结
    关于微信中的localStorage及使用cookie的解决方案
  • 原文地址:https://www.cnblogs.com/Lis-/p/11348858.html
Copyright © 2020-2023  润新知