zoukankan      html  css  js  c++  java
  • BZOJ3611: [Heoi2014]大工程

    题解:虚树模板题 维护虚树 跑树dp即可

    /**************************************************************
        Problem: 3611
        User: c20161007
        Language: C++
        Result: Accepted
        Time:15176 ms
        Memory:357336 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define ll long long
    const int MAXN=1e6+10;
    using namespace std;
    const ll inf=1e18;
    vector<int>vec[MAXN];
    int f[MAXN][21];ll sum[MAXN][21];int dep[MAXN];
    int p[MAXN],cnt;
    int st[MAXN],tot;
    vector<int>V;
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    void dfs(int v,int pre,int deep){
        dep[v]=deep;f[v][0]=pre;p[v]=++cnt;
        for(int i=0;i<vec[v].size();i++){
        int u=vec[v][i];
        if(u!=pre){
            sum[u][0]=1;
            dfs(u,v,deep+1);
        }
        }
    }
    void dfs1(int v){
        for(int i=1;i<=20;i++)sum[v][i]=sum[f[v][i-1]][i-1]+sum[v][i-1],f[v][i]=f[f[v][i-1]][i-1];
        for(int i=0;i<vec[v].size();i++){
        int u=vec[v][i];
        if(u!=f[v][0])dfs1(u);
        }
    }
    int Lca(int u,int v){
        if(dep[u]<dep[v])swap(u,v);
        int tmp=dep[u]-dep[v];
        for(int i=0;i<=20;i++)if(tmp&(1<<i))u=f[u][i];
        if(u==v)return u;
        for(int i=20;i>=0;i--){
        if(f[u][i]!=f[v][i]){
            u=f[u][i];
            v=f[v][i];
        }
        }
        return f[u][0];
    }
    void built(int x){
        V.push_back(x);
        if(!tot){st[++tot]=x;return ;}
        int lca=Lca(x,st[tot]);
      //  cout<<lca<<" "<<x<<" "<<st[tot]<<endl;
        while(tot>1&&dep[lca]<dep[st[tot-1]]){
        vec[st[tot]].push_back(st[tot-1]);
        vec[st[tot-1]].push_back(st[tot]);
        tot--;
        }
        if(dep[st[tot]]>dep[lca]){
    //  cout<<lca<<"::::"<<st[tot]<<endl;
        vec[st[tot]].push_back(lca);
        vec[lca].push_back(st[tot]);
        tot--;
        V.push_back(lca);
        }
       // cout<<tot<<"====="<<endl;
        if(!tot||dep[lca]>dep[st[tot]])st[++tot]=lca;
     //   cout<<st[tot]<<endl;
        st[++tot]=x;
    }
    ll dist(int u,int v){
        ll res=0;
       // cout<<u<<"::::::"<<v<<endl;
        for(int i=20;i>=0;i--){
        if(dep[f[u][i]]>dep[v]){
            res+=sum[u][i];
    //      cout<<u<<"::::"<<f[u][i]<<" "<<res<<endl;
            u=f[u][i];
        }
        }
        res+=sum[u][0];
        return res;
    }
    ll _f[MAXN],__f[MAXN],d[MAXN],_d[MAXN];
    int num[MAXN];
    bool vis[MAXN];
    ll ans;
    int po;
    void dfs(int x,int pre){
       // cout<<x<<" "<<pre<<endl;
        __f[x]=_d[x]=inf;_f[x]=d[x]=0;
        if(vis[x])num[x]=1;
        for(int i=0;i<vec[x].size();i++){
        if(vec[x][i]!=pre){
            dfs(vec[x][i],x);
            num[x]+=num[vec[x][i]];
            ll vul=dist(vec[x][i],x);
            ans+=1ll*vul*num[vec[x][i]]*(po-num[vec[x][i]]);
            if(d[vec[x][i]]||vis[vec[x][i]]){
            _f[x]=max(_f[x],d[x]+d[vec[x][i]]+vul);
            _f[x]=max(_f[x],_f[vec[x][i]]);
            d[x]=max(d[x],d[vec[x][i]]+vul);
            __f[x]=min(__f[x],__f[vec[x][i]]);
            __f[x]=min(__f[x],_d[x]+_d[vec[x][i]]+vul);
            _d[x]=min(_d[x],_d[vec[x][i]]+vul);
            if(vis[x])_f[x]=max(_f[x],d[vec[x][i]]+vul),__f[x]=min(__f[x],_d[vec[x][i]]+vul);
            }
        }
        }
        if(vis[x])_d[x]=0;
        if(!d[x])_d[x]=0;
    }
    int n,m;
    bool cmp(int aa,int bb){return p[aa]<p[bb];}
    int main(){
        n=read();int u,v;
        for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
       // cout<<"sb"<<endl;
        dfs(1,0,0);dfs1(1);int k;
        for(int i=1;i<=n;i++)vec[i].clear();
        m=read();
        for(int i=1;i<=m;i++){
        k=read();tot=0;ans=0;po=k;
        for(int i=1;i<=k;i++)v=read(),V.push_back(v),vis[v]=1;
        sort(V.begin(),V.end(),cmp);
        for(int i=1;i<=k;i++)built(V[i-1]);
    //  for(int i=tot;i>=1;i--)cout<<st[i]<<" ";
    //  cout<<endl;
        while(tot>1){vec[st[tot]].push_back(st[tot-1]),vec[st[tot-1]].push_back(st[tot]);tot--;}
    //  cout<<vec[1].size()<<" "<<vec[4].size()<<" "<<vec[5].size()<<endl;
    //  cout<<st[tot]<<endl;
        dfs(st[tot],f[st[tot]][0]);
        printf("%lld %lld %lld
    ",ans,__f[st[tot]],_f[st[tot]]);
        //V.clear();
        for(int i=0;i<V.size();i++)vec[V[i]].clear(),vis[V[i]]=0,num[V[i]]=0;
        V.clear();
        }
        return 0;
    }
    

    3611: [Heoi2014]大工程

    Time Limit: 60 Sec  Memory Limit: 512 MB
    Submit: 2194  Solved: 945
    [Submit][Status][Discuss]

    Description

    国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。 
    我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。 
    在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
     现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
    现在对于每个计划,我们想知道:
     1.这些新通道的代价和
     2.这些新通道中代价最小的是多少 
    3.这些新通道中代价最大的是多少

    Input

    第一行 n 表示点数。

     接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
    点从 1 开始标号。 接下来一行 q 表示计划数。
    对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
     第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。

    Output

    输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。 

     

    Sample Input

    10
    2 1
    3 2
    4 1
    5 2
    6 4
    7 5
    8 6
    9 7
    10 9
    5
    2
    5 4
    2
    10 4
    2
    5 2
    2
    6 1
    2
    6 1

    Sample Output

    3 3 3
    6 6 6
    1 1 1
    2 2 2
    2 2 2

    HINT

    n<=1000000 

    q<=50000并且保证所有k之和<=2*n
  • 相关阅读:
    pipelinewise 学习二 创建一个简单的pipeline
    pipelinewise 学习一 docker方式安装
    Supercharging your ETL with Airflow and Singer
    ubuntu中使用 alien安装rpm包
    PipelineWise illustrates the power of Singer
    pipelinewise 基于singer 指南的的数据pipeline 工具
    关于singer elt 的几篇很不错的文章
    npkill 一个方便的npm 包清理工具
    kuma docker-compose 环境试用
    kuma 学习四 策略
  • 原文地址:https://www.cnblogs.com/wang9897/p/9426446.html
Copyright © 2011-2022 走看看