• Luogu P4103 [HEOI2014]大工程


    虚树+DP

    建出虚树;第一问考虑每条边的贡献是 (w(u,v) imes sz_v imes (k-sz_v)) ;第二问第三问每次有新子树时,先计算答案,再更新最小值和最大值。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int N=1000010;
    const ll Inf=1e15;
    int n,m,k;
    int vr[N<<1],nxt[N<<1],fir[N],w[N<<1],cnt;
    int sz[N],d[N],dfn[N],pre[N],top[N],son[N],h[N],num;
    ll ans1,ans2,mx[N],mn[N],ans;
    int stk[N]; bool vis[N];
    inline void add(int u,int v,int ww) 
      {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,w[cnt]=ww;}
    inline void dfs(int u) {
      sz[u]=1,dfn[u]=++num;
      for(R i=fir[u];i;i=nxt[i]) {
        R v=vr[i];
        if(d[v]) continue;
        pre[v]=u,d[v]=d[u]+1;
        dfs(v);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u]=v;
      }
    }
    inline void dfs2(int u,int tp) {
      top[u]=tp;
      if(son[u]) dfs2(son[u],tp);
      for(R i=fir[u];i;i=nxt[i]) {
        R v=vr[i];
        if(!top[v]) dfs2(v,v);
      }
    }
    inline int lca(int u,int v) {
      while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) swap(u,v);
        u=pre[top[u]];
      } return d[u]<d[v]?u:v;
    }
    inline int dis(int u,int v) 
      {return d[u]+d[v]-2*d[lca(u,v)];}
    inline bool cmp(const int& a,const int& b) 
      {return dfn[a]<dfn[b];}
    inline void dp(int u) {
      if(vis[u]) sz[u]=1,mx[u]=mn[u]=0;
      else mx[u]=-Inf,mn[u]=Inf,sz[u]=0;
      for(R i=fir[u];i;i=nxt[i]) {
        R v=vr[i];
        dp(v);
        sz[u]+=sz[v];
        ans+=1ll*w[i]*sz[v]*(k-sz[v]);
        ans1=min(ans1,mn[u]+mn[v]+w[i]);
        mn[u]=min(mn[u],mn[v]+w[i]);
        ans2=max(ans2,mx[u]+mx[v]+w[i]);
        mx[u]=max(mx[u],mx[v]+w[i]);
      }
    }
    inline void main() {
      n=g();
      for(R i=1,u,v;i<n;++i) 
        u=g(),v=g(),add(u,v,0),add(v,u,0);
      d[1]=1,dfs(1),dfs2(1,1);
      memset(fir,0,sizeof fir);
      m=g(); 
      while(m--) {
        k=g();
        for(R i=1;i<=k;++i) h[i]=g(),vis[h[i]]=1;
        sort(h+1,h+k+1,cmp);
        R top;
        fir[1]=cnt=0;
        stk[top=1]=1;
        for(R i=1+(h[1]==1),l;i<=k;++i) {
          l=lca(stk[top],h[i]);
          if(l!=stk[top]) {
            while(dfn[l]<dfn[stk[top-1]]) 
              add(stk[top-1],stk[top],dis(stk[top-1],stk[top])),--top;
            if(dfn[l]>dfn[stk[top-1]])
              fir[l]=0,add(l,stk[top],dis(l,stk[top])),stk[top]=l;
            else add(l,stk[top],dis(l,stk[top])),--top;
          }
          fir[h[i]]=0,stk[++top]=h[i];
        }
        for(R i=1;i<top;++i) add(stk[i],stk[i+1],dis(stk[i],stk[i+1]));
        ans=0,ans1=Inf,ans2=-Inf,dp(1);
        printf("%lld %lld %lld
    ",ans,ans1,ans2);
        for(R i=1;i<=k;++i) vis[h[i]]=false;
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.17

  • 相关阅读:
    mysql 优化20点
    java function
    设计模式 概览
    Linux安装java1.8并配置环境变量
    windows下一次执行多个sql文件
    mybatis查询结果为空时的返回值问题
    Java中Json与String互转
    SSM Service自动注入失败
    本地安装Mysql5.7过程中出现的一系列问题
    解决本地工具无法连接服务器上的mysql的问题
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12207388.html
Copyright © 2020-2023  润新知