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

    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。
     

    正解:虚树+树形dp。

    对于每次询问,建立一棵虚树。在虚树上跑树形dp。这题有点麻烦,主要是dp的姿势吧。。求总数就是记录当前点size,然后加加减减就行了,求最小值就看当前点是否是关键点,如果是关键点就直接取它的子树路径最小值,否则就是它的两个儿子的子树路径最小值相加。求最大值同理。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define N (1000010)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    19 
    20 using namespace std;
    21 
    22 struct edge{ int nt,to,dis; }g[2*N];
    23 
    24 int head[N],size[N],top[N],fa[N],son[N],dis[N],dep[N],dfn[N],ed[N],a[N],st[N],vi[N],sz[N],dp1[N],dp2[N],n,m,k,u,v,q,num,cnt,ans1,ans2;
    25 ll dp[N];
    26 
    27 il int gi(){
    28     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    29     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    30 }
    31 
    32 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
    33 
    34 il int cmp(const int &a,const int &b){ return dfn[a]<dfn[b]; }
    35 
    36 il void dfs(RG int x){
    37     dp[x]=0,dp1[x]=inf,dp2[x]=0,sz[x]=vi[x];
    38     for (RG int i=head[x];i;i=g[i].nt){
    39     RG int v=g[i].to,d=dis[v]-dis[x]; dfs(v);
    40     sz[x]+=sz[v]; dp[x]+=dp[v]+(ll)sz[v]*(ll)(k-sz[v])*(ll)d;
    41     ans1=min(ans1,dp1[x]+dp1[v]+d),dp1[x]=min(dp1[x],dp1[v]+d);
    42     ans2=max(ans2,dp2[x]+dp2[v]+d),dp2[x]=max(dp2[x],dp2[v]+d);
    43     }
    44     if (vi[x]) ans1=min(ans1,dp1[x]),ans2=max(ans2,dp2[x]),dp1[x]=0;
    45     head[x]=0; return;
    46 }
    47 
    48 il void dfs1(RG int x,RG int p){
    49     dfn[x]=++cnt,dep[x]=dep[p]+1,fa[x]=p,size[x]=1;
    50     for (RG int i=head[x];i;i=g[i].nt){
    51     RG int v=g[i].to; if (v==p) continue;
    52     dis[v]=dis[x]+1; dfs1(g[i].to,x); size[x]+=size[v];
    53     if (size[son[x]]<=size[v]) son[x]=v;
    54     }
    55     ed[x]=cnt; return;
    56 }
    57 
    58 il void dfs2(RG int x,RG int p,RG int a){
    59     top[x]=a; if (son[x]) dfs2(son[x],x,a);
    60     for (RG int i=head[x];i;i=g[i].nt){
    61     RG int v=g[i].to;
    62     if (v==p || v==son[x]) continue;
    63     dfs2(v,x,v);
    64     }
    65     head[x]=0; return;
    66 }
    67 
    68 il int lca(RG int u,RG int v){
    69     while (top[u]!=top[v]){
    70     if (dep[top[u]]<dep[top[v]]) swap(u,v);
    71     u=fa[top[u]];
    72     }
    73     return dep[u]<dep[v] ? u : v;
    74 }
    75 
    76 il void work(){
    77     n=gi(); for (RG int i=1;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u); dfs1(1,0),dfs2(1,0,1); q=gi();
    78     for (RG int i=1;i<=q;++i){
    79     k=gi(),m=k; for (RG int i=1;i<=k;++i) vi[a[i]=gi()]=1; sort(a+1,a+k+1,cmp); RG int Lca=a[1];
    80     for (RG int i=2;i<=k;++i){ if (ed[a[i-1]]<dfn[a[i]]) a[++m]=lca(a[i-1],a[i]); Lca=lca(Lca,a[i]); }
    81     a[++m]=Lca; sort(a+1,a+m+1,cmp); m=unique(a+1,a+m+1)-a-1; RG int top=1; st[top]=a[1],num=0;
    82     for (RG int i=2;i<=m;++i){ while (top && ed[st[top]]<dfn[a[i]]) top--; insert(st[top],a[i]),st[++top]=a[i]; }
    83     ans1=inf,ans2=0,dfs(Lca); printf("%lld %d %d
    ",dp[Lca],ans1,ans2); for (RG int i=1;i<=m;++i) vi[a[i]]=0;
    84     }
    85     return;
    86 }
    87 
    88 int main(){
    89     File("project");
    90     work();
    91     return 0;
    92 }
  • 相关阅读:
    NTC温度检测程序(转)
    基于GPS的经纬度、方位角、距离、航向计算及基于单目视觉的距离计算!
    GPS速度和航向计算(转)
    NOR、 NAND、Raw Flash和 Managed Flash的区别(转)
    FreeModbus V1.6 主机使用说明(转)
    只要单片机具有真正唯一ID,就可以让加密坚不可摧(转)
    Java 给Word添加数字签名
    Java 获取Word中指定图片的坐标位置
    C#/VB.NET 自定义PPT动画路径
    在线编辑Excel——插入图表
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6416564.html
Copyright © 2011-2022 走看看