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
  • 相关阅读:
    一本通1486:【例题1】黑暗城堡
    洛谷P2508 [HAOI2008]圆上的整点
    codevs 3304 水果姐逛水果街Ⅰ
    洛谷P1283 平板涂色 &&一本通1445:平板涂色
    bzoj4897: [Thu Summer Camp2016]成绩单
    题解 P2719 【搞笑世界杯】
    VSCode 下go环境配置【终结版】
    Liunx(Centos 7)下一步一步部署 net core 项目
    服务器返回503(IIS Service Unavailable HTTP Error 503. The service is unavailable.)+IIS常见优化设置策略
    每日一句 Linux, 持续精进
  • 原文地址:https://www.cnblogs.com/wang9897/p/9426446.html
Copyright © 2011-2022 走看看